|
|
1.1 ! root 1: /* $Id: advansys.c,v 1.1 1999/04/26 05:54:04 tb Exp $ */ ! 2: #define ASC_VERSION "3.1E" /* AdvanSys Driver Version */ ! 3: ! 4: /* ! 5: * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters ! 6: * ! 7: * Copyright (c) 1995-1998 Advanced System Products, Inc. ! 8: * All Rights Reserved. ! 9: * ! 10: * Redistribution and use in source and binary forms, with or without ! 11: * modification, are permitted provided that redistributions of source ! 12: * code retain the above copyright notice and this comment without ! 13: * modification. ! 14: * ! 15: * There is an AdvanSys Linux WWW page at: ! 16: * http://www.advansys.com/linux.html ! 17: * ! 18: * The latest version of the AdvanSys driver is available at: ! 19: * ftp://ftp.advansys.com/pub/linux/linux.tgz ! 20: * ! 21: * Please send questions, comments, bug reports to: ! 22: * [email protected] (Bob Frey) ! 23: */ ! 24: ! 25: /* ! 26: ! 27: Documentation for the AdvanSys Driver ! 28: ! 29: A. Linux Kernel Testing ! 30: B. Adapters Supported by this Driver ! 31: C. Linux v1.2.X - Directions for Adding the AdvanSys Driver ! 32: D. Linux v1.3.1 - v1.3.57 - Directions for Adding the AdvanSys Driver ! 33: E. Linux v1.3.58 and Newer - Upgrading the AdvanSys Driver ! 34: F. Source Comments ! 35: G. Driver Compile Time Options and Debugging ! 36: H. Driver LILO Option ! 37: I. Release History ! 38: J. Known Problems or Issues ! 39: K. Credits ! 40: L. AdvanSys Contact Information ! 41: ! 42: A. Linux Kernel Testing ! 43: ! 44: This driver has been tested in the following Linux kernels: v1.2.13, ! 45: v1.3.57, v2.0.33, v2.1.77. These kernel versions are major releases ! 46: of Linux or the latest Linux kernel versions available when this version ! 47: of the driver was released. The driver should also work in earlier ! 48: versions of the Linux kernel. Beginning with v1.3.58 the AdvanSys driver ! 49: is included with all Linux kernels. Please refer to sections C, D, and ! 50: E for instructions on adding or upgrading the AdvanSys driver. ! 51: ! 52: B. Adapters Supported by this Driver ! 53: ! 54: AdvanSys (Advanced System Products, Inc.) manufactures the following ! 55: RISC-based, Bus-Mastering, Fast (10 Mhz) and Ultra (20 Mhz) Narrow ! 56: (8-bit transfer) SCSI Host Adapters for the ISA, EISA, VL, and PCI ! 57: buses and RISC-based, Bus-Mastering, Ultra (20 Mhz) Wide (16-bit ! 58: transfer) SCSI Host Adapters for the PCI bus. ! 59: ! 60: The CDB counts below indicate the number of SCSI CDB (Command ! 61: Descriptor Block) requests that can be stored in the RISC chip ! 62: cache and board LRAM. A CDB is a single SCSI command. The driver ! 63: detect routine will display the number of CDBs available for each ! 64: adapter detected. The number of CDBs used by the driver can be ! 65: lowered in the BIOS by changing the 'Host Queue Size' adapter setting. ! 66: ! 67: Connectivity Products: ! 68: ABP510/5150 - Bus-Master ISA (240 CDB) (Footnote 1) ! 69: ABP5140 - Bus-Master ISA PnP (16 CDB) (Footnote 1, 3) ! 70: ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) (Footnote 4) ! 71: ABP920 - Bus-Master PCI (16 CDB) ! 72: ABP930 - Bus-Master PCI (16 CDB) (Footnote 5) ! 73: ABP930U - Bus-Master PCI Ultra (16 CDB) ! 74: ABP930UA - Bus-Master PCI Ultra (16 CDB) ! 75: ABP960 - Bus-Master PCI MAC/PC (16 CDB) (Footnote 2) ! 76: ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB) (Footnote 2) ! 77: ! 78: Single Channel Products: ! 79: ABP542 - Bus-Master ISA with floppy (240 CDB) ! 80: ABP742 - Bus-Master EISA (240 CDB) ! 81: ABP842 - Bus-Master VL (240 CDB) ! 82: ABP940 - Bus-Master PCI (240 CDB) ! 83: ABP940U - Bus-Master PCI Ultra (240 CDB) ! 84: ABP970 - Bus-Master PCI MAC/PC (240 CDB) ! 85: ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB) ! 86: ABP940UW - Bus-Master PCI Ultra-Wide (240 CDB) ! 87: ! 88: Multi Channel Products: ! 89: ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel) ! 90: ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel) ! 91: ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel) ! 92: ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel) ! 93: ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel) ! 94: ! 95: Footnotes: ! 96: 1. This board has been shipped by HP with the 4020i CD-R drive. ! 97: The board has no BIOS so it cannot control a boot device, but ! 98: it can control any secondary SCSI device. ! 99: 2. This board has been sold by Iomega as a Jaz Jet PCI adapter. ! 100: 3. This board has been sold by SIIG as the i540 SpeedMaster. ! 101: 4. This board has been sold by SIIG as the i542 SpeedMaster. ! 102: 5. This board has been sold by SIIG as the Fast SCSI Pro PCI. ! 103: ! 104: C. Linux v1.2.X - Directions for Adding the AdvanSys Driver ! 105: ! 106: These directions apply to v1.2.13. For versions that follow v1.2.13. ! 107: but precede v1.3.57 some of the changes for Linux v1.3.X listed ! 108: below may need to be modified or included. A patch is available ! 109: for v1.2.13 from the AdvanSys WWW and FTP sites. ! 110: ! 111: There are two source files: advansys.h and advansys.c. Copy ! 112: both of these files to the directory /usr/src/linux/drivers/scsi. ! 113: ! 114: 1. Add the following line to /usr/src/linux/arch/i386/config.in ! 115: after "comment 'SCSI low-level drivers'": ! 116: ! 117: bool 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS y ! 118: ! 119: 2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c ! 120: after "#include "hosts.h"": ! 121: ! 122: #ifdef CONFIG_SCSI_ADVANSYS ! 123: #include "advansys.h" ! 124: #endif ! 125: ! 126: and after "static Scsi_Host_Template builtin_scsi_hosts[] =": ! 127: ! 128: #ifdef CONFIG_SCSI_ADVANSYS ! 129: ADVANSYS, ! 130: #endif ! 131: ! 132: 3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile: ! 133: ! 134: ifdef CONFIG_SCSI_ADVANSYS ! 135: SCSI_SRCS := $(SCSI_SRCS) advansys.c ! 136: SCSI_OBJS := $(SCSI_OBJS) advansys.o ! 137: else ! 138: SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) advansys.o ! 139: endif ! 140: ! 141: 4. (Optional) If you would like to enable the LILO command line ! 142: and /etc/lilo.conf 'advansys' option, make the following changes. ! 143: This option can be used to disable I/O port scanning or to limit ! 144: I/O port scanning to specific addresses. Refer to the 'Driver ! 145: LILO Option' section below. Add the following lines to ! 146: /usr/src/linux/init/main.c in the prototype section: ! 147: ! 148: extern void advansys_setup(char *str, int *ints); ! 149: ! 150: and add the following lines to the bootsetups[] array. ! 151: ! 152: #ifdef CONFIG_SCSI_ADVANSYS ! 153: { "advansys=", advansys_setup }, ! 154: #endif ! 155: ! 156: 5. If you have the HP 4020i CD-R driver and Linux v1.2.X you should ! 157: add a fix to the CD-ROM target driver. This fix will allow ! 158: you to mount CDs with the iso9660 file system. Linux v1.3.X ! 159: already has this fix. In the file /usr/src/linux/drivers/scsi/sr.c ! 160: and function get_sectorsize() after the line: ! 161: ! 162: if(scsi_CDs[i].sector_size == 0) scsi_CDs[i].sector_size = 2048; ! 163: ! 164: add the following line: ! 165: ! 166: if(scsi_CDs[i].sector_size == 2340) scsi_CDs[i].sector_size = 2048; ! 167: ! 168: 6. In the directory /usr/src/linux run 'make config' to configure ! 169: the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to ! 170: make the kernel. If the AdvanSys driver is not configured, then ! 171: a loadable module can be built by running 'make modules' and ! 172: 'make modules_install'. Use 'insmod' and 'rmmod' to install ! 173: and remove advansys.o. ! 174: ! 175: D. Linux v1.3.1 - v1.3.57 - Directions for Adding the AdvanSys Driver ! 176: ! 177: These directions apply to v1.3.57. For versions that precede v1.3.57 ! 178: some of these changes may need to be modified or eliminated. A patch ! 179: is available for v1.3.57 from the AdvanSys WWW and FTP sites. ! 180: Beginning with v1.3.58 this driver is included with the Linux ! 181: distribution eliminating the need for making any changes. ! 182: ! 183: There are two source files: advansys.h and advansys.c. Copy ! 184: both of these files to the directory /usr/src/linux/drivers/scsi. ! 185: ! 186: 1. Add the following line to /usr/src/linux/drivers/scsi/Config.in ! 187: after "comment 'SCSI low-level drivers'": ! 188: ! 189: dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI ! 190: ! 191: 2. Add the following lines to /usr/src/linux/drivers/scsi/hosts.c ! 192: after "#include "hosts.h"": ! 193: ! 194: #ifdef CONFIG_SCSI_ADVANSYS ! 195: #include "advansys.h" ! 196: #endif ! 197: ! 198: and after "static Scsi_Host_Template builtin_scsi_hosts[] =": ! 199: ! 200: #ifdef CONFIG_SCSI_ADVANSYS ! 201: ADVANSYS, ! 202: #endif ! 203: ! 204: 3. Add the following lines to /usr/src/linux/drivers/scsi/Makefile: ! 205: ! 206: ifeq ($(CONFIG_SCSI_ADVANSYS),y) ! 207: L_OBJS += advansys.o ! 208: else ! 209: ifeq ($(CONFIG_SCSI_ADVANSYS),m) ! 210: M_OBJS += advansys.o ! 211: endif ! 212: endif ! 213: ! 214: 4. Add the following line to /usr/src/linux/include/linux/proc_fs.h ! 215: in the enum scsi_directory_inos array: ! 216: ! 217: PROC_SCSI_ADVANSYS, ! 218: ! 219: 5. (Optional) If you would like to enable the LILO command line ! 220: and /etc/lilo.conf 'advansys' option, make the following changes. ! 221: This option can be used to disable I/O port scanning or to limit ! 222: I/O port scanning to specific addresses. Refer to the 'Driver ! 223: LILO Option' section below. Add the following lines to ! 224: /usr/src/linux/init/main.c in the prototype section: ! 225: ! 226: extern void advansys_setup(char *str, int *ints); ! 227: ! 228: and add the following lines to the bootsetups[] array. ! 229: ! 230: #ifdef CONFIG_SCSI_ADVANSYS ! 231: { "advansys=", advansys_setup }, ! 232: #endif ! 233: ! 234: 6. In the directory /usr/src/linux run 'make config' to configure ! 235: the AdvanSys driver, then run 'make vmlinux' or 'make zlilo' to ! 236: make the kernel. If the AdvanSys driver is not configured, then ! 237: a loadable module can be built by running 'make modules' and ! 238: 'make modules_install'. Use 'insmod' and 'rmmod' to install ! 239: and remove advansys.o. ! 240: ! 241: E. Linux v1.3.58 and Newer - Upgrading the AdvanSys Driver ! 242: ! 243: To upgrade the AdvanSys driver in a Linux v1.3.58 and newer ! 244: kernel, first check the version of the current driver. The ! 245: version is defined by the manifest constant ASC_VERSION at ! 246: the beginning of advansys.c. The new driver should have a ! 247: ASC_VERSION value greater than the current version. To install ! 248: the new driver rename advansys.c and advansys.h in the Linux ! 249: kernel source tree drivers/scsi directory to different names ! 250: or save them to a different directory in case you want to revert ! 251: to the old version of the driver. After the old driver is saved ! 252: copy the new advansys.c and advansys.h to drivers/scsi, rebuild ! 253: the kernel, and install the new kernel. No other changes are needed. ! 254: ! 255: F. Source Comments ! 256: ! 257: 1. Use tab stops set to 4 for the source files. For vi use 'se tabstops=4'. ! 258: ! 259: 2. This driver should be maintained in multiple files. But to make ! 260: it easier to include with Linux and to follow Linux conventions, ! 261: the whole driver is maintained in the source files advansys.h and ! 262: advansys.c. In this file logical sections of the driver begin with ! 263: a comment that contains '---'. The following are the logical sections ! 264: of the driver below. ! 265: ! 266: --- Linux Version ! 267: --- Linux Include Files ! 268: --- Driver Options ! 269: --- Debugging Header ! 270: --- Asc Library Constants and Macros ! 271: --- Adv Library Constants and Macros ! 272: --- Driver Constants and Macros ! 273: --- Driver Structures ! 274: --- Driver Data ! 275: --- Driver Function Prototypes ! 276: --- Linux 'Scsi_Host_Template' and advansys_setup() Functions ! 277: --- Loadable Driver Support ! 278: --- Miscellaneous Driver Functions ! 279: --- Functions Required by the Asc Library ! 280: --- Functions Required by the Adv Library ! 281: --- Tracing and Debugging Functions ! 282: --- Asc Library Functions ! 283: --- Adv Library Functions ! 284: ! 285: 3. The string 'XXX' is used to flag code that needs to be re-written ! 286: or that contains a problem that needs to be addressed. ! 287: ! 288: 4. I have stripped comments from and reformatted the source for the ! 289: Asc Library and Adv Library to reduce the size of this file. This ! 290: source can be found under the following headings. The Asc Library ! 291: is used to support Narrow Boards. The Adv Library is used to ! 292: support Wide Boards. ! 293: ! 294: --- Asc Library Constants and Macros ! 295: --- Adv Library Constants and Macros ! 296: --- Asc Library Functions ! 297: --- Adv Library Functions ! 298: ! 299: G. Driver Compile Time Options and Debugging ! 300: ! 301: In this source file the following constants can be defined. They are ! 302: defined in the source below. Both of these options are enabled by ! 303: default. ! 304: ! 305: 1. ADVANSYS_ASSERT - Enable driver assertions (Def: Enabled) ! 306: ! 307: Enabling this option adds assertion logic statements to the ! 308: driver. If an assertion fails a message will be displayed to ! 309: the console, but the system will continue to operate. Any ! 310: assertions encountered should be reported to the person ! 311: responsible for the driver. Assertion statements may proactively ! 312: detect problems with the driver and facilitate fixing these ! 313: problems. Enabling assertions will add a small overhead to the ! 314: execution of the driver. ! 315: ! 316: 2. ADVANSYS_DEBUG - Enable driver debugging (Def: Disabled) ! 317: ! 318: Enabling this option adds tracing functions to the driver and ! 319: the ability to set a driver tracing level at boot time. This ! 320: option will also export symbols not required outside the driver to ! 321: the kernel name space. This option is very useful for debugging ! 322: the driver, but it will add to the size of the driver execution ! 323: image and add overhead to the execution of the driver. ! 324: ! 325: The amount of debugging output can be controlled with the global ! 326: variable 'asc_dbglvl'. The higher the number the more output. By ! 327: default the debug level is 0. ! 328: ! 329: If the driver is loaded at boot time and the LILO Driver Option ! 330: is included in the system, the debug level can be changed by ! 331: specifying a 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port. The ! 332: first three hex digits of the pseudo I/O Port must be set to ! 333: 'deb' and the fourth hex digit specifies the debug level: 0 - F. ! 334: The following command line will look for an adapter at 0x330 ! 335: and set the debug level to 2. ! 336: ! 337: linux advansys=0x330,0,0,0,0xdeb2 ! 338: ! 339: If the driver is built as a loadable module this variable can be ! 340: defined when the driver is loaded. The following insmod command ! 341: will set the debug level to one. ! 342: ! 343: insmod advansys.o asc_dbglvl=1 ! 344: ! 345: Debugging Message Levels: ! 346: 0: Errors Only ! 347: 1: High-Level Tracing ! 348: 2-N: Verbose Tracing ! 349: ! 350: I don't know the approved way for turning on printk()s to the ! 351: console. Here's a program I use to do this. Debug output is ! 352: logged in /var/adm/messages. ! 353: ! 354: main() ! 355: { ! 356: syscall(103, 7, 0, 0); ! 357: } ! 358: ! 359: I found that increasing LOG_BUF_LEN to 40960 in kernel/printk.c ! 360: prevents most level 1 debug messages from being lost. ! 361: ! 362: 3. ADVANSYS_STATS - Enable statistics (Def: Enabled >= v1.3.0) ! 363: ! 364: Enabling this option adds statistics collection and display ! 365: through /proc to the driver. The information is useful for ! 366: monitoring driver and device performance. It will add to the ! 367: size of the driver execution image and add minor overhead to ! 368: the execution of the driver. ! 369: ! 370: Statistics are maintained on a per adapter basis. Driver entry ! 371: point call counts and transfer size counts are maintained. ! 372: Statistics are only available for kernels greater than or equal ! 373: to v1.3.0 with the CONFIG_PROC_FS (/proc) file system configured. ! 374: ! 375: AdvanSys SCSI adapter files have the following path name format: ! 376: ! 377: /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)] ! 378: ! 379: This information can be displayed with cat. For example: ! 380: ! 381: cat /proc/scsi/advansys/0 ! 382: ! 383: When ADVANSYS_STATS is not defined the AdvanSys /proc files only ! 384: contain adapter and device configuration information. ! 385: ! 386: H. Driver LILO Option ! 387: ! 388: If init/main.c is modified as described in the 'Directions for Adding ! 389: the AdvanSys Driver to Linux' section (B.4.) above, the driver will ! 390: recognize the 'advansys' LILO command line and /etc/lilo.conf option. ! 391: This option can be used to either disable I/O port scanning or to limit ! 392: scanning to 1 - 4 I/O ports. Regardless of the option setting EISA and ! 393: PCI boards will still be searched for and detected. This option only ! 394: affects searching for ISA and VL boards. ! 395: ! 396: Examples: ! 397: 1. Eliminate I/O port scanning: ! 398: boot: linux advansys= ! 399: or ! 400: boot: linux advansys=0x0 ! 401: 2. Limit I/O port scanning to one I/O port: ! 402: boot: linux advansys=0x110 ! 403: 3. Limit I/O port scanning to four I/O ports: ! 404: boot: linux advansys=0x110,0x210,0x230,0x330 ! 405: ! 406: For a loadable module the same effect can be achieved by setting ! 407: the 'asc_iopflag' variable and 'asc_ioport' array when loading ! 408: the driver, e.g. ! 409: ! 410: insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330 ! 411: ! 412: If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_IOPORT_PROBE + 1) ! 413: I/O Port may be added to specify the driver debug level. Refer to ! 414: the 'Driver Compile Time Options and Debugging' section above for ! 415: more information. ! 416: ! 417: I. Release History ! 418: ! 419: BETA-1.0 (12/23/95): ! 420: First Release ! 421: ! 422: BETA-1.1 (12/28/95): ! 423: 1. Prevent advansys_detect() from being called twice. ! 424: 2. Add LILO 0xdeb[0-f] option to set 'asc_dbglvl'. ! 425: ! 426: 1.2 (1/12/96): ! 427: 1. Prevent re-entrancy in the interrupt handler which ! 428: resulted in the driver hanging Linux. ! 429: 2. Fix problem that prevented ABP-940 cards from being ! 430: recognized on some PCI motherboards. ! 431: 3. Add support for the ABP-5140 PnP ISA card. ! 432: 4. Fix check condition return status. ! 433: 5. Add conditionally compiled code for Linux v1.3.X. ! 434: ! 435: 1.3 (2/23/96): ! 436: 1. Fix problem in advansys_biosparam() that resulted in the ! 437: wrong drive geometry being returned for drives > 1GB with ! 438: extended translation enabled. ! 439: 2. Add additional tracing during device initialization. ! 440: 3. Change code that only applies to ISA PnP adapter. ! 441: 4. Eliminate 'make dep' warning. ! 442: 5. Try to fix problem with handling resets by increasing their ! 443: timeout value. ! 444: ! 445: 1.4 (5/8/96): ! 446: 1. Change definitions to eliminate conflicts with other subsystems. ! 447: 2. Add versioning code for the shared interrupt changes. ! 448: 3. Eliminate problem in asc_rmqueue() with iterating after removing ! 449: a request. ! 450: 4. Remove reset request loop problem from the "Known Problems or ! 451: Issues" section. This problem was isolated and fixed in the ! 452: mid-level SCSI driver. ! 453: ! 454: 1.5 (8/8/96): ! 455: 1. Add support for ABP-940U (PCI Ultra) adapter. ! 456: 2. Add support for IRQ sharing by setting the SA_SHIRQ flag for ! 457: request_irq and supplying a dev_id pointer to both request_irq() ! 458: and free_irq(). ! 459: 3. In AscSearchIOPortAddr11() restore a call to check_region() which ! 460: should be used before I/O port probing. ! 461: 4. Fix bug in asc_prt_hex() which resulted in the displaying ! 462: the wrong data. ! 463: 5. Incorporate miscellaneous Asc Library bug fixes and new microcode. ! 464: 6. Change driver versioning to be specific to each Linux sub-level. ! 465: 7. Change statistics gathering to be per adapter instead of global ! 466: to the driver. ! 467: 8. Add more information and statistics to the adapter /proc file: ! 468: /proc/scsi/advansys[0...]. ! 469: 9. Remove 'cmd_per_lun' from the "Known Problems or Issues" list. ! 470: This problem has been addressed with the SCSI mid-level changes ! 471: made in v1.3.89. The advansys_select_queue_depths() function ! 472: was added for the v1.3.89 changes. ! 473: ! 474: 1.6 (9/10/96): ! 475: 1. Incorporate miscellaneous Asc Library bug fixes and new microcode. ! 476: ! 477: 1.7 (9/25/96): ! 478: 1. Enable clustering and optimize the setting of the maximum number ! 479: of scatter gather elements for any particular board. Clustering ! 480: increases CPU utilization, but results in a relatively larger ! 481: increase in I/O throughput. ! 482: 2. Improve the performance of the request queuing functions by ! 483: adding a last pointer to the queue structure. ! 484: 3. Correct problems with reset and abort request handling that ! 485: could have hung or crashed Linux. ! 486: 4. Add more information to the adapter /proc file: ! 487: /proc/scsi/advansys[0...]. ! 488: 5. Remove the request timeout issue form the driver issues list. ! 489: 6. Miscellaneous documentation additions and changes. ! 490: ! 491: 1.8 (10/4/96): ! 492: 1. Make changes to handle the new v2.1.0 kernel memory mapping ! 493: in which a kernel virtual address may not be equivalent to its ! 494: bus or DMA memory address. ! 495: 2. Change abort and reset request handling to make it yet even ! 496: more robust. ! 497: 3. Try to mitigate request starvation by sending ordered requests ! 498: to heavily loaded, tag queuing enabled devices. ! 499: 4. Maintain statistics on request response time. ! 500: 5. Add request response time statistics and other information to ! 501: the adapter /proc file: /proc/scsi/advansys[0...]. ! 502: ! 503: 1.9 (10/21/96): ! 504: 1. Add conditionally compiled code (ASC_QUEUE_FLOW_CONTROL) to ! 505: make use of mid-level SCSI driver device queue depth flow ! 506: control mechanism. This will eliminate aborts caused by a ! 507: device being unable to keep up with requests and eliminate ! 508: repeat busy or QUEUE FULL status returned by a device. ! 509: 2. Incorporate miscellaneous Asc Library bug fixes. ! 510: 3. To allow the driver to work in kernels with broken module ! 511: support set 'cmd_per_lun' if the driver is compiled as a ! 512: module. This change affects kernels v1.3.89 to present. ! 513: 4. Remove PCI BIOS address from the driver banner. The PCI BIOS ! 514: is relocated by the motherboard BIOS and its new address can ! 515: not be determined by the driver. ! 516: 5. Add mid-level SCSI queue depth information to the adapter ! 517: /proc file: /proc/scsi/advansys[0...]. ! 518: ! 519: 2.0 (11/14/96): ! 520: 1. Change allocation of global structures used for device ! 521: initialization to guarantee they are in DMA-able memory. ! 522: Previously when the driver was loaded as a module these ! 523: structures might not have been in DMA-able memory, causing ! 524: device initialization to fail. ! 525: ! 526: 2.1 (12/30/96): ! 527: 1. In advansys_reset(), if the request is a synchronous reset ! 528: request, even if the request serial number has changed, then ! 529: complete the request. ! 530: 2. Add Asc Library bug fixes including new microcode. ! 531: 3. Clear inquiry buffer before using it. ! 532: 4. Correct ifdef typo. ! 533: ! 534: 2.2 (1/15/97): ! 535: 1. Add Asc Library bug fixes including new microcode. ! 536: 2. Add synchronous data transfer rate information to the ! 537: adapter /proc file: /proc/scsi/advansys[0...]. ! 538: 3. Change ADVANSYS_DEBUG to be disabled by default. This ! 539: will reduce the size of the driver image, eliminate execution ! 540: overhead, and remove unneeded symbols from the kernel symbol ! 541: space that were previously added by the driver. ! 542: 4. Add new compile-time option ADVANSYS_ASSERT for assertion ! 543: code that used to be defined within ADVANSYS_DEBUG. This ! 544: option is enabled by default. ! 545: ! 546: 2.8 (5/26/97): ! 547: 1. Change version number to 2.8 to synchronize the Linux driver ! 548: version numbering with other AdvanSys drivers. ! 549: 2. Reformat source files without tabs to present the same view ! 550: of the file to everyone regardless of the editor tab setting ! 551: being used. ! 552: 3. Add Asc Library bug fixes. ! 553: ! 554: 3.1A (1/8/98): ! 555: 1. Change version number to 3.1 to indicate that support for ! 556: Ultra-Wide adapters (ABP-940UW) is included in this release. ! 557: 2. Add Asc Library (Narrow Board) bug fixes. ! 558: 3. Report an underrun condition with the host status byte set ! 559: to DID_UNDERRUN. Currently DID_UNDERRUN is defined to 0 which ! 560: causes the underrun condition to be ignored. When Linux defines ! 561: its own DID_UNDERRUN the constant defined in this file can be ! 562: removed. ! 563: 4. Add patch to AscWaitTixISRDone(). ! 564: 5. Add support for up to 16 different AdvanSys host adapter SCSI ! 565: channels in one system. This allows four cards with four channels ! 566: to be used in one system. ! 567: ! 568: 3.1B (1/9/98): ! 569: 1. Handle that PCI register base addresses are not always page ! 570: aligned even though ioremap() requires that the address argument ! 571: be page aligned. ! 572: ! 573: 3.1C (1/10/98): ! 574: 1. Update latest BIOS version checked for from the /proc file. ! 575: 2. Don't set microcode SDTR variable at initialization. Instead ! 576: wait until device capabilities have been detected from an Inquiry ! 577: command. ! 578: ! 579: 3.1D (1/21/98): ! 580: 1. Improve performance when the driver is compiled as module by ! 581: allowing up to 64 scatter-gather elements instead of 8. ! 582: ! 583: 3.1E (5/1/98): ! 584: 1. Set time delay in AscWaitTixISRDone() to 1000 ms. ! 585: 2. Include SMP locking changes. ! 586: 3. For v2.1.93 and newer kernels use CONFIG_PCI and new PCI BIOS ! 587: access functions. ! 588: 4. Update board serial number printing. ! 589: 5. Try allocating an IRQ both with and without the SA_INTERRUPT ! 590: flag set to allow IRQ sharing with drivers that do not set ! 591: the SA_INTERRUPT flag. Also display a more descriptive error ! 592: message if request_irq() fails. ! 593: 5. Update to latest Asc and Adv Libraries. ! 594: ! 595: J. Known Problems or Issues ! 596: ! 597: 1. Remove conditional constants (ASC_QUEUE_FLOW_CONTROL) around ! 598: the queue depth flow control code when mid-level SCSI changes ! 599: are included in Linux. ! 600: ! 601: K. Credits ! 602: ! 603: Nathan Hartwell <[email protected]> provided the directions and ! 604: basis for the Linux v1.3.X changes which were included in the ! 605: 1.2 release. ! 606: ! 607: Thomas E Zerucha <[email protected]> pointed out a bug ! 608: in advansys_biosparam() which was fixed in the 1.3 release. ! 609: ! 610: Erik Ratcliffe <[email protected]> has done testing of the ! 611: AdvanSys driver in the Caldera releases. ! 612: ! 613: Rik van Riel <[email protected]> provided a patch to ! 614: AscWaitTixISRDone() which he found necessary to make the ! 615: driver work with a SCSI-1 disk. ! 616: ! 617: Mark Moran <[email protected]> has helped test Ultra-Wide ! 618: support in the 3.1A driver. ! 619: ! 620: L. AdvanSys Contact Information ! 621: ! 622: Mail: Advanced System Products, Inc. ! 623: 1150 Ringwood Court ! 624: San Jose, CA 95131 ! 625: Operator: 1-408-383-9400 ! 626: FAX: 1-408-383-9612 ! 627: Tech Support: 1-800-525-7440/1-408-467-2930 ! 628: BBS: 1-408-383-9540 (14400,N,8,1) ! 629: Interactive FAX: 1-408-383-9753 ! 630: Customer Direct Sales: 1-800-525-7443/1-408-383-5777 ! 631: Tech Support E-Mail: [email protected] ! 632: FTP Site: ftp.advansys.com (login: anonymous) ! 633: Web Site: http://www.advansys.com ! 634: ! 635: */ ! 636: ! 637: ! 638: /* ! 639: * --- Linux Version ! 640: */ ! 641: ! 642: /* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */ ! 643: #define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S)) ! 644: ! 645: #ifndef LINUX_VERSION_CODE ! 646: #include <linux/version.h> ! 647: #endif /* LINUX_VERSION_CODE */ ! 648: ! 649: ! 650: /* ! 651: * --- Linux Include Files ! 652: */ ! 653: ! 654: #include <linux/config.h> ! 655: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 656: #ifdef MODULE ! 657: #include <linux/module.h> ! 658: #endif /* MODULE */ ! 659: #endif /* version >= v1.3.0 */ ! 660: #include <linux/string.h> ! 661: #include <linux/sched.h> ! 662: #include <linux/kernel.h> ! 663: #include <linux/head.h> ! 664: #include <linux/types.h> ! 665: #include <linux/ioport.h> ! 666: #include <linux/delay.h> ! 667: #include <linux/malloc.h> ! 668: #include <linux/mm.h> ! 669: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 670: #include <linux/proc_fs.h> ! 671: #endif /* version >= v1.3.0 */ ! 672: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,23) ! 673: #include <linux/init.h> ! 674: #endif /* version >= v2.1.23 */ ! 675: #include <asm/io.h> ! 676: #include <asm/system.h> ! 677: #include <asm/dma.h> ! 678: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0) ! 679: #include "../block/blk.h" ! 680: #else /* version >= v1.3.0 */ ! 681: #include <linux/blk.h> ! 682: #include <linux/stat.h> ! 683: #endif /* version >= v1.3.0 */ ! 684: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,95) ! 685: #include <asm/spinlock.h> ! 686: #endif /* version >= 2.1.95 */ ! 687: #include "scsi.h" ! 688: #include "hosts.h" ! 689: #include "sd.h" ! 690: #include "advansys.h" ! 691: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,93) ! 692: #ifdef CONFIG_PCI ! 693: #include <linux/pci.h> ! 694: #endif /* CONFIG_PCI */ ! 695: #else /* version < v2.1.93 */ ! 696: /* ! 697: * For earlier than v2.1.93 the driver has its own PCI configuration. ! 698: * If PCI is not needed in a kernel before v2.1.93 this define can be ! 699: * turned-off to make the driver object smaller. ! 700: */ ! 701: #define ASC_CONFIG_PCI ! 702: #endif /* version < v2.1.93 */ ! 703: ! 704: /* ! 705: * If Linux eventually defines a DID_UNDERRUN, the constant here can be ! 706: * removed. The current value of zero for DID_UNDERRUN results in underrun ! 707: * conditions being ignored. ! 708: */ ! 709: #define DID_UNDERRUN 0 ! 710: ! 711: ! 712: /* ! 713: * --- Driver Options ! 714: */ ! 715: ! 716: /* Enable driver assertions. */ ! 717: #define ADVANSYS_ASSERT ! 718: ! 719: /* Enable driver tracing. */ ! 720: /* #define ADVANSYS_DEBUG */ ! 721: ! 722: /* ! 723: * Because of no /proc to display them, statistics are disabled ! 724: * for versions prior to v1.3.0. ! 725: */ ! 726: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0) ! 727: #undef ADVANSYS_STATS /* Disable statistics */ ! 728: #else /* version >= v1.3.0 */ ! 729: #define ADVANSYS_STATS /* Enable statistics. */ ! 730: #endif /* version >= v1.3.0 */ ! 731: ! 732: ! 733: /* ! 734: * --- Debugging Header ! 735: */ ! 736: ! 737: #ifdef ADVANSYS_DEBUG ! 738: #define STATIC ! 739: #else /* ADVANSYS_DEBUG */ ! 740: #define STATIC static ! 741: #endif /* ADVANSYS_DEBUG */ ! 742: ! 743: ! 744: /* ! 745: * --- Asc Library Constants and Macros ! 746: */ ! 747: ! 748: #define ASC_LIB_VERSION_MAJOR 1 ! 749: #define ASC_LIB_VERSION_MINOR 22 ! 750: #define ASC_LIB_SERIAL_NUMBER 113 ! 751: ! 752: typedef unsigned char uchar; ! 753: ! 754: #ifndef NULL ! 755: #define NULL (0) ! 756: #endif ! 757: #ifndef TRUE ! 758: #define TRUE (1) ! 759: #endif ! 760: #ifndef FALSE ! 761: #define FALSE (0) ! 762: #endif ! 763: #define REG register ! 764: #define rchar REG __s8 ! 765: #define rshort REG __s16 ! 766: #define rint REG __s32 ! 767: #define rlong REG __s32 ! 768: #define ruchar REG __u8 ! 769: #define rushort REG __u16 ! 770: #define ruint REG __u32 ! 771: #define rulong REG __u32 ! 772: #define NULLPTR (void *)0 ! 773: #define FNULLPTR (void *)0UL ! 774: #define EOF (-1) ! 775: #define EOS '\0' ! 776: #define ERR (-1) ! 777: #define UB_ERR (uchar)(0xFF) ! 778: #define UW_ERR (uint)(0xFFFF) ! 779: #define UL_ERR (ulong)(0xFFFFFFFFUL) ! 780: #define iseven_word(val) ((((uint)val) & (uint)0x0001) == 0) ! 781: #define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0) ! 782: #define toeven_word(val) (((uint)val) & (uint)0xFFFE) ! 783: #define biton(val, bits) (((uint)(val >> bits) & (uint)0x0001) != 0) ! 784: #define bitoff(val, bits) (((uint)(val >> bits) & (uint)0x0001) == 0) ! 785: #define lbiton(val, bits) (((ulong)(val >> bits) & (ulong)0x00000001UL) != 0) ! 786: #define lbitoff(val, bits) (((ulong)(val >> bits) & (ulong)0x00000001UL) == 0) ! 787: #define absh(val) ((val) < 0 ? -(val) : (val)) ! 788: #define swapbyte(ch) ((((ch) << 4) | ((ch) >> 4))) ! 789: #ifndef GBYTE ! 790: #define GBYTE (0x40000000UL) ! 791: #endif ! 792: #ifndef MBYTE ! 793: #define MBYTE (0x100000UL) ! 794: #endif ! 795: #ifndef KBYTE ! 796: #define KBYTE (0x400) ! 797: #endif ! 798: #define HI_BYTE(x) (*((__u8 *)(&x)+1)) ! 799: #define LO_BYTE(x) (*((__u8 *)&x)) ! 800: #define HI_WORD(x) (*((__u16 *)(&x)+1)) ! 801: #define LO_WORD(x) (*((__u16 *)&x)) ! 802: #ifndef MAKEWORD ! 803: #define MAKEWORD(lo, hi) ((__u16) (((__u16) lo) | ((__u16) hi << 8))) ! 804: #endif ! 805: #ifndef MAKELONG ! 806: #define MAKELONG(lo, hi) ((__u32) (((__u32) lo) | ((__u32) hi << 16))) ! 807: #endif ! 808: #define SwapWords(dWord) ((__u32) ((dWord >> 16) | (dWord << 16))) ! 809: #define SwapBytes(word) ((__u16) ((word >> 8) | (word << 8))) ! 810: #define BigToLittle(dWord) ((__u32) (SwapWords(MAKELONG(SwapBytes(LO_WORD(dWord)), SwapBytes(HI_WORD(dWord)))))) ! 811: #define LittleToBig(dWord) BigToLittle(dWord) ! 812: #define AscPCIConfigVendorIDRegister 0x0000 ! 813: #define AscPCIConfigDeviceIDRegister 0x0002 ! 814: #define AscPCIConfigCommandRegister 0x0004 ! 815: #define AscPCIConfigStatusRegister 0x0006 ! 816: #define AscPCIConfigRevisionIDRegister 0x0008 ! 817: #define AscPCIConfigCacheSize 0x000C ! 818: #define AscPCIConfigLatencyTimer 0x000D ! 819: #define AscPCIIOBaseRegister 0x0010 ! 820: #define AscPCICmdRegBits_IOMemBusMaster 0x0007 ! 821: #define ASC_PCI_ID2BUS(id) ((id) & 0xFF) ! 822: #define ASC_PCI_ID2DEV(id) (((id) >> 11) & 0x1F) ! 823: #define ASC_PCI_ID2FUNC(id) (((id) >> 8) & 0x7) ! 824: #define ASC_PCI_MKID(bus, dev, func) ((((dev) & 0x1F) << 11) | (((func) & 0x7) << 8) | ((bus) & 0xFF)) ! 825: #define ASC_PCI_VENDORID 0x10CD ! 826: #define ASC_PCI_DEVICEID_1200A 0x1100 ! 827: #define ASC_PCI_DEVICEID_1200B 0x1200 ! 828: #define ASC_PCI_DEVICEID_ULTRA 0x1300 ! 829: #define ASC_PCI_REVISION_3150 0x02 ! 830: #define ASC_PCI_REVISION_3050 0x03 ! 831: ! 832: #define ASC_DVCLIB_CALL_DONE (1) ! 833: #define ASC_DVCLIB_CALL_FAILED (0) ! 834: #define ASC_DVCLIB_CALL_ERROR (-1) ! 835: ! 836: #define PortAddr unsigned short /* port address size */ ! 837: #define Ptr2Func ulong ! 838: #define inp(port) inb(port) ! 839: #define inpw(port) inw(port) ! 840: #define inpl(port) inl(port) ! 841: #define outp(port, byte) outb((byte), (port)) ! 842: #define outpw(port, word) outw((word), (port)) ! 843: #define outpl(port, long) outl((long), (port)) ! 844: #define ASC_MAX_SG_QUEUE 7 ! 845: #define ASC_MAX_SG_LIST SG_ALL ! 846: ! 847: #define ASC_CS_TYPE unsigned short ! 848: #ifndef asc_ptr_type ! 849: #define asc_ptr_type ! 850: #endif ! 851: ! 852: #ifndef ASC_GET_PTR2FUNC ! 853: #define ASC_GET_PTR2FUNC(fun) (Ptr2Func)(fun) ! 854: #endif ! 855: #define FLIP_BYTE_NIBBLE(x) (((x<<4)& 0xFF) | (x>>4)) ! 856: #define ASC_IS_ISA (0x0001) ! 857: #define ASC_IS_ISAPNP (0x0081) ! 858: #define ASC_IS_EISA (0x0002) ! 859: #define ASC_IS_PCI (0x0004) ! 860: #define ASC_IS_PCI_ULTRA (0x0104) ! 861: #define ASC_IS_PCMCIA (0x0008) ! 862: #define ASC_IS_MCA (0x0020) ! 863: #define ASC_IS_VL (0x0040) ! 864: #define ASC_ISA_PNP_PORT_ADDR (0x279) ! 865: #define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800) ! 866: #define ASC_IS_WIDESCSI_16 (0x0100) ! 867: #define ASC_IS_WIDESCSI_32 (0x0200) ! 868: #define ASC_IS_BIG_ENDIAN (0x8000) ! 869: #define ASC_CHIP_MIN_VER_VL (0x01) ! 870: #define ASC_CHIP_MAX_VER_VL (0x07) ! 871: #define ASC_CHIP_MIN_VER_PCI (0x09) ! 872: #define ASC_CHIP_MAX_VER_PCI (0x0F) ! 873: #define ASC_CHIP_VER_PCI_BIT (0x08) ! 874: #define ASC_CHIP_MIN_VER_ISA (0x11) ! 875: #define ASC_CHIP_MIN_VER_ISA_PNP (0x21) ! 876: #define ASC_CHIP_MAX_VER_ISA (0x27) ! 877: #define ASC_CHIP_VER_ISA_BIT (0x30) ! 878: #define ASC_CHIP_VER_ISAPNP_BIT (0x20) ! 879: #define ASC_CHIP_VER_ASYN_BUG (0x21) ! 880: #define ASC_CHIP_VER_PCI 0x08 ! 881: #define ASC_CHIP_VER_PCI_ULTRA_3150 (ASC_CHIP_VER_PCI | 0x02) ! 882: #define ASC_CHIP_VER_PCI_ULTRA_3050 (ASC_CHIP_VER_PCI | 0x03) ! 883: #define ASC_CHIP_MIN_VER_EISA (0x41) ! 884: #define ASC_CHIP_MAX_VER_EISA (0x47) ! 885: #define ASC_CHIP_VER_EISA_BIT (0x40) ! 886: #define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3) ! 887: #define ASC_MAX_LIB_SUPPORTED_ISA_CHIP_VER 0x21 ! 888: #define ASC_MAX_LIB_SUPPORTED_PCI_CHIP_VER 0x0A ! 889: #define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL) ! 890: #define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL) ! 891: #define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL) ! 892: #define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL) ! 893: #define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL) ! 894: #define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL) ! 895: #define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL) ! 896: #define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL) ! 897: #ifndef inpw_noswap ! 898: #define inpw_noswap(port) inpw(port) ! 899: #endif ! 900: #ifndef outpw_noswap ! 901: #define outpw_noswap(port, data) outpw(port, data) ! 902: #endif ! 903: #define ASC_SCSI_ID_BITS 3 ! 904: #define ASC_SCSI_TIX_TYPE uchar ! 905: #define ASC_ALL_DEVICE_BIT_SET 0xFF ! 906: #ifdef ASC_WIDESCSI_16 ! 907: #undef ASC_SCSI_ID_BITS ! 908: #define ASC_SCSI_ID_BITS 4 ! 909: #define ASC_ALL_DEVICE_BIT_SET 0xFFFF ! 910: #endif ! 911: #ifdef ASC_WIDESCSI_32 ! 912: #undef ASC_SCSI_ID_BITS ! 913: #define ASC_SCSI_ID_BITS 5 ! 914: #define ASC_ALL_DEVICE_BIT_SET 0xFFFFFFFFL ! 915: #endif ! 916: #if ASC_SCSI_ID_BITS == 3 ! 917: #define ASC_SCSI_BIT_ID_TYPE uchar ! 918: #define ASC_MAX_TID 7 ! 919: #define ASC_MAX_LUN 7 ! 920: #define ASC_SCSI_WIDTH_BIT_SET 0xFF ! 921: #elif ASC_SCSI_ID_BITS == 4 ! 922: #define ASC_SCSI_BIT_ID_TYPE ushort ! 923: #define ASC_MAX_TID 15 ! 924: #define ASC_MAX_LUN 7 ! 925: #define ASC_SCSI_WIDTH_BIT_SET 0xFFFF ! 926: #elif ASC_SCSI_ID_BITS == 5 ! 927: #define ASC_SCSI_BIT_ID_TYPE ulong ! 928: #define ASC_MAX_TID 31 ! 929: #define ASC_MAX_LUN 7 ! 930: #define ASC_SCSI_WIDTH_BIT_SET 0xFFFFFFFF ! 931: #else ! 932: #error ASC_SCSI_ID_BITS definition is wrong ! 933: #endif ! 934: #define ASC_MAX_SENSE_LEN 32 ! 935: #define ASC_MIN_SENSE_LEN 14 ! 936: #define ASC_MAX_CDB_LEN 12 ! 937: #define ASC_SCSI_RESET_HOLD_TIME_US 60 ! 938: #define SCSICMD_TestUnitReady 0x00 ! 939: #define SCSICMD_Rewind 0x01 ! 940: #define SCSICMD_Rezero 0x01 ! 941: #define SCSICMD_RequestSense 0x03 ! 942: #define SCSICMD_Format 0x04 ! 943: #define SCSICMD_FormatUnit 0x04 ! 944: #define SCSICMD_Read6 0x08 ! 945: #define SCSICMD_Write6 0x0A ! 946: #define SCSICMD_Seek6 0x0B ! 947: #define SCSICMD_Inquiry 0x12 ! 948: #define SCSICMD_Verify6 0x13 ! 949: #define SCSICMD_ModeSelect6 0x15 ! 950: #define SCSICMD_ModeSense6 0x1A ! 951: #define SCSICMD_StartStopUnit 0x1B ! 952: #define SCSICMD_LoadUnloadTape 0x1B ! 953: #define SCSICMD_ReadCapacity 0x25 ! 954: #define SCSICMD_Read10 0x28 ! 955: #define SCSICMD_Write10 0x2A ! 956: #define SCSICMD_Seek10 0x2B ! 957: #define SCSICMD_Erase10 0x2C ! 958: #define SCSICMD_WriteAndVerify10 0x2E ! 959: #define SCSICMD_Verify10 0x2F ! 960: #define SCSICMD_WriteBuffer 0x3B ! 961: #define SCSICMD_ReadBuffer 0x3C ! 962: #define SCSICMD_ReadLong 0x3E ! 963: #define SCSICMD_WriteLong 0x3F ! 964: #define SCSICMD_ReadTOC 0x43 ! 965: #define SCSICMD_ReadHeader 0x44 ! 966: #define SCSICMD_ModeSelect10 0x55 ! 967: #define SCSICMD_ModeSense10 0x5A ! 968: #define SCSI_TYPE_DASD 0x00 ! 969: #define SCSI_TYPE_SASD 0x01 ! 970: #define SCSI_TYPE_PRN 0x02 ! 971: #define SCSI_TYPE_PROC 0x03 ! 972: #define SCSI_TYPE_WORM 0x04 ! 973: #define SCSI_TYPE_CDROM 0x05 ! 974: #define SCSI_TYPE_SCANNER 0x06 ! 975: #define SCSI_TYPE_OPTMEM 0x07 ! 976: #define SCSI_TYPE_MED_CHG 0x08 ! 977: #define SCSI_TYPE_COMM 0x09 ! 978: #define SCSI_TYPE_UNKNOWN 0x1F ! 979: #define SCSI_TYPE_NO_DVC 0xFF ! 980: #define ASC_SCSIDIR_NOCHK 0x00 ! 981: #define ASC_SCSIDIR_T2H 0x08 ! 982: #define ASC_SCSIDIR_H2T 0x10 ! 983: #define ASC_SCSIDIR_NODATA 0x18 ! 984: #define SCSI_SENKEY_NO_SENSE 0x00 ! 985: #define SCSI_SENKEY_UNDEFINED 0x01 ! 986: #define SCSI_SENKEY_NOT_READY 0x02 ! 987: #define SCSI_SENKEY_MEDIUM_ERR 0x03 ! 988: #define SCSI_SENKEY_HW_ERR 0x04 ! 989: #define SCSI_SENKEY_ILLEGAL 0x05 ! 990: #define SCSI_SENKEY_ATTENTION 0x06 ! 991: #define SCSI_SENKEY_PROTECTED 0x07 ! 992: #define SCSI_SENKEY_BLANK 0x08 ! 993: #define SCSI_SENKEY_V_UNIQUE 0x09 ! 994: #define SCSI_SENKEY_CPY_ABORT 0x0A ! 995: #define SCSI_SENKEY_ABORT 0x0B ! 996: #define SCSI_SENKEY_EQUAL 0x0C ! 997: #define SCSI_SENKEY_VOL_OVERFLOW 0x0D ! 998: #define SCSI_SENKEY_MISCOMP 0x0E ! 999: #define SCSI_SENKEY_RESERVED 0x0F ! 1000: #define SCSI_ASC_NOMEDIA 0x3A ! 1001: #define ASC_SRB_HOST(x) ((uchar)((uchar)(x) >> 4)) ! 1002: #define ASC_SRB_TID(x) ((uchar)((uchar)(x) & (uchar)0x0F)) ! 1003: #define ASC_SRB_LUN(x) ((uchar)((uint)(x) >> 13)) ! 1004: #define PUT_CDB1(x) ((uchar)((uint)(x) >> 8)) ! 1005: #define SS_GOOD 0x00 ! 1006: #define SS_CHK_CONDITION 0x02 ! 1007: #define SS_CONDITION_MET 0x04 ! 1008: #define SS_TARGET_BUSY 0x08 ! 1009: #define SS_INTERMID 0x10 ! 1010: #define SS_INTERMID_COND_MET 0x14 ! 1011: #define SS_RSERV_CONFLICT 0x18 ! 1012: #define SS_CMD_TERMINATED 0x22 ! 1013: #define SS_QUEUE_FULL 0x28 ! 1014: #define MS_CMD_DONE 0x00 ! 1015: #define MS_EXTEND 0x01 ! 1016: #define MS_SDTR_LEN 0x03 ! 1017: #define MS_SDTR_CODE 0x01 ! 1018: #define MS_WDTR_LEN 0x02 ! 1019: #define MS_WDTR_CODE 0x03 ! 1020: #define MS_MDP_LEN 0x05 ! 1021: #define MS_MDP_CODE 0x00 ! 1022: #define M1_SAVE_DATA_PTR 0x02 ! 1023: #define M1_RESTORE_PTRS 0x03 ! 1024: #define M1_DISCONNECT 0x04 ! 1025: #define M1_INIT_DETECTED_ERR 0x05 ! 1026: #define M1_ABORT 0x06 ! 1027: #define M1_MSG_REJECT 0x07 ! 1028: #define M1_NO_OP 0x08 ! 1029: #define M1_MSG_PARITY_ERR 0x09 ! 1030: #define M1_LINK_CMD_DONE 0x0A ! 1031: #define M1_LINK_CMD_DONE_WFLAG 0x0B ! 1032: #define M1_BUS_DVC_RESET 0x0C ! 1033: #define M1_ABORT_TAG 0x0D ! 1034: #define M1_CLR_QUEUE 0x0E ! 1035: #define M1_INIT_RECOVERY 0x0F ! 1036: #define M1_RELEASE_RECOVERY 0x10 ! 1037: #define M1_KILL_IO_PROC 0x11 ! 1038: #define M2_QTAG_MSG_SIMPLE 0x20 ! 1039: #define M2_QTAG_MSG_HEAD 0x21 ! 1040: #define M2_QTAG_MSG_ORDERED 0x22 ! 1041: #define M2_IGNORE_WIDE_RESIDUE 0x23 ! 1042: ! 1043: typedef struct { ! 1044: uchar peri_dvc_type:5; ! 1045: uchar peri_qualifier:3; ! 1046: } ASC_SCSI_INQ0; ! 1047: ! 1048: typedef struct { ! 1049: uchar dvc_type_modifier:7; ! 1050: uchar rmb:1; ! 1051: } ASC_SCSI_INQ1; ! 1052: ! 1053: typedef struct { ! 1054: uchar ansi_apr_ver:3; ! 1055: uchar ecma_ver:3; ! 1056: uchar iso_ver:2; ! 1057: } ASC_SCSI_INQ2; ! 1058: ! 1059: typedef struct { ! 1060: uchar rsp_data_fmt:4; ! 1061: uchar res:2; ! 1062: uchar TemIOP:1; ! 1063: uchar aenc:1; ! 1064: } ASC_SCSI_INQ3; ! 1065: ! 1066: typedef struct { ! 1067: uchar StfRe:1; ! 1068: uchar CmdQue:1; ! 1069: uchar Reserved:1; ! 1070: uchar Linked:1; ! 1071: uchar Sync:1; ! 1072: uchar WBus16:1; ! 1073: uchar WBus32:1; ! 1074: uchar RelAdr:1; ! 1075: } ASC_SCSI_INQ7; ! 1076: ! 1077: typedef struct { ! 1078: ASC_SCSI_INQ0 byte0; ! 1079: ASC_SCSI_INQ1 byte1; ! 1080: ASC_SCSI_INQ2 byte2; ! 1081: ASC_SCSI_INQ3 byte3; ! 1082: uchar add_len; ! 1083: uchar res1; ! 1084: uchar res2; ! 1085: ASC_SCSI_INQ7 byte7; ! 1086: uchar vendor_id[8]; ! 1087: uchar product_id[16]; ! 1088: uchar product_rev_level[4]; ! 1089: } ASC_SCSI_INQUIRY; ! 1090: ! 1091: typedef struct asc_req_sense { ! 1092: uchar err_code:7; ! 1093: uchar info_valid:1; ! 1094: uchar segment_no; ! 1095: uchar sense_key:4; ! 1096: uchar reserved_bit:1; ! 1097: uchar sense_ILI:1; ! 1098: uchar sense_EOM:1; ! 1099: uchar file_mark:1; ! 1100: uchar info1[4]; ! 1101: uchar add_sense_len; ! 1102: uchar cmd_sp_info[4]; ! 1103: uchar asc; ! 1104: uchar ascq; ! 1105: uchar fruc; ! 1106: uchar sks_byte0:7; ! 1107: uchar sks_valid:1; ! 1108: uchar sks_bytes[2]; ! 1109: uchar notused[2]; ! 1110: uchar ex_sense_code; ! 1111: uchar info2[4]; ! 1112: } ASC_REQ_SENSE; ! 1113: ! 1114: #define ASC_SG_LIST_PER_Q 7 ! 1115: #define QS_FREE 0x00 ! 1116: #define QS_READY 0x01 ! 1117: #define QS_DISC1 0x02 ! 1118: #define QS_DISC2 0x04 ! 1119: #define QS_BUSY 0x08 ! 1120: #define QS_ABORTED 0x40 ! 1121: #define QS_DONE 0x80 ! 1122: #define QC_NO_CALLBACK 0x01 ! 1123: #define QC_SG_SWAP_QUEUE 0x02 ! 1124: #define QC_SG_HEAD 0x04 ! 1125: #define QC_DATA_IN 0x08 ! 1126: #define QC_DATA_OUT 0x10 ! 1127: #define QC_URGENT 0x20 ! 1128: #define QC_MSG_OUT 0x40 ! 1129: #define QC_REQ_SENSE 0x80 ! 1130: #define QCSG_SG_XFER_LIST 0x02 ! 1131: #define QCSG_SG_XFER_MORE 0x04 ! 1132: #define QCSG_SG_XFER_END 0x08 ! 1133: #define QD_IN_PROGRESS 0x00 ! 1134: #define QD_NO_ERROR 0x01 ! 1135: #define QD_ABORTED_BY_HOST 0x02 ! 1136: #define QD_WITH_ERROR 0x04 ! 1137: #define QD_INVALID_REQUEST 0x80 ! 1138: #define QD_INVALID_HOST_NUM 0x81 ! 1139: #define QD_INVALID_DEVICE 0x82 ! 1140: #define QD_ERR_INTERNAL 0xFF ! 1141: #define QHSTA_NO_ERROR 0x00 ! 1142: #define QHSTA_M_SEL_TIMEOUT 0x11 ! 1143: #define QHSTA_M_DATA_OVER_RUN 0x12 ! 1144: #define QHSTA_M_DATA_UNDER_RUN 0x12 ! 1145: #define QHSTA_M_UNEXPECTED_BUS_FREE 0x13 ! 1146: #define QHSTA_M_BAD_BUS_PHASE_SEQ 0x14 ! 1147: #define QHSTA_D_QDONE_SG_LIST_CORRUPTED 0x21 ! 1148: #define QHSTA_D_ASC_DVC_ERROR_CODE_SET 0x22 ! 1149: #define QHSTA_D_HOST_ABORT_FAILED 0x23 ! 1150: #define QHSTA_D_EXE_SCSI_Q_FAILED 0x24 ! 1151: #define QHSTA_D_EXE_SCSI_Q_BUSY_TIMEOUT 0x25 ! 1152: #define QHSTA_D_ASPI_NO_BUF_POOL 0x26 ! 1153: #define QHSTA_M_WTM_TIMEOUT 0x41 ! 1154: #define QHSTA_M_BAD_CMPL_STATUS_IN 0x42 ! 1155: #define QHSTA_M_NO_AUTO_REQ_SENSE 0x43 ! 1156: #define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44 ! 1157: #define QHSTA_M_TARGET_STATUS_BUSY 0x45 ! 1158: #define QHSTA_M_BAD_TAG_CODE 0x46 ! 1159: #define QHSTA_M_BAD_QUEUE_FULL_OR_BUSY 0x47 ! 1160: #define QHSTA_M_HUNG_REQ_SCSI_BUS_RESET 0x48 ! 1161: #define QHSTA_D_LRAM_CMP_ERROR 0x81 ! 1162: #define QHSTA_M_MICRO_CODE_ERROR_HALT 0xA1 ! 1163: #define ASC_FLAG_SCSIQ_REQ 0x01 ! 1164: #define ASC_FLAG_BIOS_SCSIQ_REQ 0x02 ! 1165: #define ASC_FLAG_BIOS_ASYNC_IO 0x04 ! 1166: #define ASC_FLAG_SRB_LINEAR_ADDR 0x08 ! 1167: #define ASC_FLAG_WIN16 0x10 ! 1168: #define ASC_FLAG_WIN32 0x20 ! 1169: #define ASC_FLAG_ISA_OVER_16MB 0x40 ! 1170: #define ASC_FLAG_DOS_VM_CALLBACK 0x80 ! 1171: #define ASC_TAG_FLAG_EXTRA_BYTES 0x10 ! 1172: #define ASC_TAG_FLAG_DISABLE_DISCONNECT 0x04 ! 1173: #define ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX 0x08 ! 1174: #define ASC_TAG_FLAG_DISABLE_CHK_COND_INT_HOST 0x40 ! 1175: #define ASC_SCSIQ_CPY_BEG 4 ! 1176: #define ASC_SCSIQ_SGHD_CPY_BEG 2 ! 1177: #define ASC_SCSIQ_B_FWD 0 ! 1178: #define ASC_SCSIQ_B_BWD 1 ! 1179: #define ASC_SCSIQ_B_STATUS 2 ! 1180: #define ASC_SCSIQ_B_QNO 3 ! 1181: #define ASC_SCSIQ_B_CNTL 4 ! 1182: #define ASC_SCSIQ_B_SG_QUEUE_CNT 5 ! 1183: #define ASC_SCSIQ_D_DATA_ADDR 8 ! 1184: #define ASC_SCSIQ_D_DATA_CNT 12 ! 1185: #define ASC_SCSIQ_B_SENSE_LEN 20 ! 1186: #define ASC_SCSIQ_DONE_INFO_BEG 22 ! 1187: #define ASC_SCSIQ_D_SRBPTR 22 ! 1188: #define ASC_SCSIQ_B_TARGET_IX 26 ! 1189: #define ASC_SCSIQ_B_CDB_LEN 28 ! 1190: #define ASC_SCSIQ_B_TAG_CODE 29 ! 1191: #define ASC_SCSIQ_W_VM_ID 30 ! 1192: #define ASC_SCSIQ_DONE_STATUS 32 ! 1193: #define ASC_SCSIQ_HOST_STATUS 33 ! 1194: #define ASC_SCSIQ_SCSI_STATUS 34 ! 1195: #define ASC_SCSIQ_CDB_BEG 36 ! 1196: #define ASC_SCSIQ_DW_REMAIN_XFER_ADDR 56 ! 1197: #define ASC_SCSIQ_DW_REMAIN_XFER_CNT 60 ! 1198: #define ASC_SCSIQ_B_SG_WK_QP 49 ! 1199: #define ASC_SCSIQ_B_SG_WK_IX 50 ! 1200: #define ASC_SCSIQ_W_REQ_COUNT 52 ! 1201: #define ASC_SCSIQ_B_LIST_CNT 6 ! 1202: #define ASC_SCSIQ_B_CUR_LIST_CNT 7 ! 1203: #define ASC_SGQ_B_SG_CNTL 4 ! 1204: #define ASC_SGQ_B_SG_HEAD_QP 5 ! 1205: #define ASC_SGQ_B_SG_LIST_CNT 6 ! 1206: #define ASC_SGQ_B_SG_CUR_LIST_CNT 7 ! 1207: #define ASC_SGQ_LIST_BEG 8 ! 1208: #define ASC_DEF_SCSI1_QNG 4 ! 1209: #define ASC_MAX_SCSI1_QNG 4 ! 1210: #define ASC_DEF_SCSI2_QNG 16 ! 1211: #define ASC_MAX_SCSI2_QNG 32 ! 1212: #define ASC_TAG_CODE_MASK 0x23 ! 1213: #define ASC_STOP_REQ_RISC_STOP 0x01 ! 1214: #define ASC_STOP_ACK_RISC_STOP 0x03 ! 1215: #define ASC_STOP_CLEAN_UP_BUSY_Q 0x10 ! 1216: #define ASC_STOP_CLEAN_UP_DISC_Q 0x20 ! 1217: #define ASC_STOP_HOST_REQ_RISC_HALT 0x40 ! 1218: #define ASC_TIDLUN_TO_IX(tid, lun) (ASC_SCSI_TIX_TYPE)((tid) + ((lun)<<ASC_SCSI_ID_BITS)) ! 1219: #define ASC_TID_TO_TARGET_ID(tid) (ASC_SCSI_BIT_ID_TYPE)(0x01 << (tid)) ! 1220: #define ASC_TIX_TO_TARGET_ID(tix) (0x01 << ((tix) & ASC_MAX_TID)) ! 1221: #define ASC_TIX_TO_TID(tix) ((tix) & ASC_MAX_TID) ! 1222: #define ASC_TID_TO_TIX(tid) ((tid) & ASC_MAX_TID) ! 1223: #define ASC_TIX_TO_LUN(tix) (((tix) >> ASC_SCSI_ID_BITS) & ASC_MAX_LUN) ! 1224: #define ASC_QNO_TO_QADDR(q_no) ((ASC_QADR_BEG)+((int)(q_no) << 6)) ! 1225: ! 1226: typedef struct asc_scisq_1 { ! 1227: uchar status; ! 1228: uchar q_no; ! 1229: uchar cntl; ! 1230: uchar sg_queue_cnt; ! 1231: uchar target_id; ! 1232: uchar target_lun; ! 1233: ulong data_addr; ! 1234: ulong data_cnt; ! 1235: ulong sense_addr; ! 1236: uchar sense_len; ! 1237: uchar extra_bytes; ! 1238: } ASC_SCSIQ_1; ! 1239: ! 1240: typedef struct asc_scisq_2 { ! 1241: ulong srb_ptr; ! 1242: uchar target_ix; ! 1243: uchar flag; ! 1244: uchar cdb_len; ! 1245: uchar tag_code; ! 1246: ushort vm_id; ! 1247: } ASC_SCSIQ_2; ! 1248: ! 1249: typedef struct asc_scsiq_3 { ! 1250: uchar done_stat; ! 1251: uchar host_stat; ! 1252: uchar scsi_stat; ! 1253: uchar scsi_msg; ! 1254: } ASC_SCSIQ_3; ! 1255: ! 1256: typedef struct asc_scsiq_4 { ! 1257: uchar cdb[ASC_MAX_CDB_LEN]; ! 1258: uchar y_first_sg_list_qp; ! 1259: uchar y_working_sg_qp; ! 1260: uchar y_working_sg_ix; ! 1261: uchar y_res; ! 1262: ushort x_req_count; ! 1263: ushort x_reconnect_rtn; ! 1264: ulong x_saved_data_addr; ! 1265: ulong x_saved_data_cnt; ! 1266: } ASC_SCSIQ_4; ! 1267: ! 1268: typedef struct asc_q_done_info { ! 1269: ASC_SCSIQ_2 d2; ! 1270: ASC_SCSIQ_3 d3; ! 1271: uchar q_status; ! 1272: uchar q_no; ! 1273: uchar cntl; ! 1274: uchar sense_len; ! 1275: uchar extra_bytes; ! 1276: uchar res; ! 1277: ulong remain_bytes; ! 1278: } ASC_QDONE_INFO; ! 1279: ! 1280: typedef struct asc_sg_list { ! 1281: ulong addr; ! 1282: ulong bytes; ! 1283: } ASC_SG_LIST; ! 1284: ! 1285: typedef struct asc_sg_head { ! 1286: ushort entry_cnt; ! 1287: ushort queue_cnt; ! 1288: ushort entry_to_copy; ! 1289: ushort res; ! 1290: ASC_SG_LIST sg_list[ASC_MAX_SG_LIST]; ! 1291: } ASC_SG_HEAD; ! 1292: ! 1293: #define ASC_MIN_SG_LIST 2 ! 1294: ! 1295: typedef struct asc_min_sg_head { ! 1296: ushort entry_cnt; ! 1297: ushort queue_cnt; ! 1298: ushort entry_to_copy; ! 1299: ushort res; ! 1300: ASC_SG_LIST sg_list[ASC_MIN_SG_LIST]; ! 1301: } ASC_MIN_SG_HEAD; ! 1302: ! 1303: #define QCX_SORT (0x0001) ! 1304: #define QCX_COALEASE (0x0002) ! 1305: ! 1306: typedef struct asc_scsi_q { ! 1307: ASC_SCSIQ_1 q1; ! 1308: ASC_SCSIQ_2 q2; ! 1309: uchar *cdbptr; ! 1310: ASC_SG_HEAD *sg_head; ! 1311: } ASC_SCSI_Q; ! 1312: ! 1313: typedef struct asc_scsi_req_q { ! 1314: ASC_SCSIQ_1 r1; ! 1315: ASC_SCSIQ_2 r2; ! 1316: uchar *cdbptr; ! 1317: ASC_SG_HEAD *sg_head; ! 1318: uchar *sense_ptr; ! 1319: ASC_SCSIQ_3 r3; ! 1320: uchar cdb[ASC_MAX_CDB_LEN]; ! 1321: uchar sense[ASC_MIN_SENSE_LEN]; ! 1322: } ASC_SCSI_REQ_Q; ! 1323: ! 1324: typedef struct asc_scsi_bios_req_q { ! 1325: ASC_SCSIQ_1 r1; ! 1326: ASC_SCSIQ_2 r2; ! 1327: uchar *cdbptr; ! 1328: ASC_SG_HEAD *sg_head; ! 1329: uchar *sense_ptr; ! 1330: ASC_SCSIQ_3 r3; ! 1331: uchar cdb[ASC_MAX_CDB_LEN]; ! 1332: uchar sense[ASC_MIN_SENSE_LEN]; ! 1333: } ASC_SCSI_BIOS_REQ_Q; ! 1334: ! 1335: typedef struct asc_risc_q { ! 1336: uchar fwd; ! 1337: uchar bwd; ! 1338: ASC_SCSIQ_1 i1; ! 1339: ASC_SCSIQ_2 i2; ! 1340: ASC_SCSIQ_3 i3; ! 1341: ASC_SCSIQ_4 i4; ! 1342: } ASC_RISC_Q; ! 1343: ! 1344: typedef struct asc_sg_list_q { ! 1345: uchar seq_no; ! 1346: uchar q_no; ! 1347: uchar cntl; ! 1348: uchar sg_head_qp; ! 1349: uchar sg_list_cnt; ! 1350: uchar sg_cur_list_cnt; ! 1351: } ASC_SG_LIST_Q; ! 1352: ! 1353: typedef struct asc_risc_sg_list_q { ! 1354: uchar fwd; ! 1355: uchar bwd; ! 1356: ASC_SG_LIST_Q sg; ! 1357: ASC_SG_LIST sg_list[7]; ! 1358: } ASC_RISC_SG_LIST_Q; ! 1359: ! 1360: #define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL ! 1361: #define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024 ! 1362: #define ASCQ_ERR_NO_ERROR 0 ! 1363: #define ASCQ_ERR_IO_NOT_FOUND 1 ! 1364: #define ASCQ_ERR_LOCAL_MEM 2 ! 1365: #define ASCQ_ERR_CHKSUM 3 ! 1366: #define ASCQ_ERR_START_CHIP 4 ! 1367: #define ASCQ_ERR_INT_TARGET_ID 5 ! 1368: #define ASCQ_ERR_INT_LOCAL_MEM 6 ! 1369: #define ASCQ_ERR_HALT_RISC 7 ! 1370: #define ASCQ_ERR_GET_ASPI_ENTRY 8 ! 1371: #define ASCQ_ERR_CLOSE_ASPI 9 ! 1372: #define ASCQ_ERR_HOST_INQUIRY 0x0A ! 1373: #define ASCQ_ERR_SAVED_SRB_BAD 0x0B ! 1374: #define ASCQ_ERR_QCNTL_SG_LIST 0x0C ! 1375: #define ASCQ_ERR_Q_STATUS 0x0D ! 1376: #define ASCQ_ERR_WR_SCSIQ 0x0E ! 1377: #define ASCQ_ERR_PC_ADDR 0x0F ! 1378: #define ASCQ_ERR_SYN_OFFSET 0x10 ! 1379: #define ASCQ_ERR_SYN_XFER_TIME 0x11 ! 1380: #define ASCQ_ERR_LOCK_DMA 0x12 ! 1381: #define ASCQ_ERR_UNLOCK_DMA 0x13 ! 1382: #define ASCQ_ERR_VDS_CHK_INSTALL 0x14 ! 1383: #define ASCQ_ERR_MICRO_CODE_HALT 0x15 ! 1384: #define ASCQ_ERR_SET_LRAM_ADDR 0x16 ! 1385: #define ASCQ_ERR_CUR_QNG 0x17 ! 1386: #define ASCQ_ERR_SG_Q_LINKS 0x18 ! 1387: #define ASCQ_ERR_SCSIQ_PTR 0x19 ! 1388: #define ASCQ_ERR_ISR_RE_ENTRY 0x1A ! 1389: #define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B ! 1390: #define ASCQ_ERR_ISR_ON_CRITICAL 0x1C ! 1391: #define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D ! 1392: #define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E ! 1393: #define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F ! 1394: #define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20 ! 1395: #define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21 ! 1396: #define ASCQ_ERR_SEND_SCSI_Q 0x22 ! 1397: #define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23 ! 1398: #define ASCQ_ERR_RESET_SDTR 0x24 ! 1399: #define ASC_WARN_NO_ERROR 0x0000 ! 1400: #define ASC_WARN_IO_PORT_ROTATE 0x0001 ! 1401: #define ASC_WARN_EEPROM_CHKSUM 0x0002 ! 1402: #define ASC_WARN_IRQ_MODIFIED 0x0004 ! 1403: #define ASC_WARN_AUTO_CONFIG 0x0008 ! 1404: #define ASC_WARN_CMD_QNG_CONFLICT 0x0010 ! 1405: #define ASC_WARN_EEPROM_RECOVER 0x0020 ! 1406: #define ASC_WARN_CFG_MSW_RECOVER 0x0040 ! 1407: #define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 ! 1408: #define ASC_IERR_WRITE_EEPROM 0x0001 ! 1409: #define ASC_IERR_MCODE_CHKSUM 0x0002 ! 1410: #define ASC_IERR_SET_PC_ADDR 0x0004 ! 1411: #define ASC_IERR_START_STOP_CHIP 0x0008 ! 1412: #define ASC_IERR_IRQ_NO 0x0010 ! 1413: #define ASC_IERR_SET_IRQ_NO 0x0020 ! 1414: #define ASC_IERR_CHIP_VERSION 0x0040 ! 1415: #define ASC_IERR_SET_SCSI_ID 0x0080 ! 1416: #define ASC_IERR_GET_PHY_ADDR 0x0100 ! 1417: #define ASC_IERR_BAD_SIGNATURE 0x0200 ! 1418: #define ASC_IERR_NO_BUS_TYPE 0x0400 ! 1419: #define ASC_IERR_SCAM 0x0800 ! 1420: #define ASC_IERR_SET_SDTR 0x1000 ! 1421: #define ASC_IERR_RW_LRAM 0x8000 ! 1422: #define ASC_DEF_IRQ_NO 10 ! 1423: #define ASC_MAX_IRQ_NO 15 ! 1424: #define ASC_MIN_IRQ_NO 10 ! 1425: #define ASC_MIN_REMAIN_Q (0x02) ! 1426: #define ASC_DEF_MAX_TOTAL_QNG (0xF0) ! 1427: #define ASC_MIN_TAG_Q_PER_DVC (0x04) ! 1428: #define ASC_DEF_TAG_Q_PER_DVC (0x04) ! 1429: #define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q ! 1430: #define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q)) ! 1431: #define ASC_MAX_TOTAL_QNG 240 ! 1432: #define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16 ! 1433: #define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8 ! 1434: #define ASC_MAX_PCI_INRAM_TOTAL_QNG 20 ! 1435: #define ASC_MAX_INRAM_TAG_QNG 16 ! 1436: #define ASC_IOADR_TABLE_MAX_IX 11 ! 1437: #define ASC_IOADR_GAP 0x10 ! 1438: #define ASC_SEARCH_IOP_GAP 0x10 ! 1439: #define ASC_MIN_IOP_ADDR (PortAddr)0x0100 ! 1440: #define ASC_MAX_IOP_ADDR (PortAddr)0x3F0 ! 1441: #define ASC_IOADR_1 (PortAddr)0x0110 ! 1442: #define ASC_IOADR_2 (PortAddr)0x0130 ! 1443: #define ASC_IOADR_3 (PortAddr)0x0150 ! 1444: #define ASC_IOADR_4 (PortAddr)0x0190 ! 1445: #define ASC_IOADR_5 (PortAddr)0x0210 ! 1446: #define ASC_IOADR_6 (PortAddr)0x0230 ! 1447: #define ASC_IOADR_7 (PortAddr)0x0250 ! 1448: #define ASC_IOADR_8 (PortAddr)0x0330 ! 1449: #define ASC_IOADR_DEF ASC_IOADR_8 ! 1450: #define ASC_LIB_SCSIQ_WK_SP 256 ! 1451: #define ASC_MAX_SYN_XFER_NO 16 ! 1452: #define ASC_SYN_MAX_OFFSET 0x0F ! 1453: #define ASC_DEF_SDTR_OFFSET 0x0F ! 1454: #define ASC_DEF_SDTR_INDEX 0x00 ! 1455: #define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02 ! 1456: #define SYN_XFER_NS_0 25 ! 1457: #define SYN_XFER_NS_1 30 ! 1458: #define SYN_XFER_NS_2 35 ! 1459: #define SYN_XFER_NS_3 40 ! 1460: #define SYN_XFER_NS_4 50 ! 1461: #define SYN_XFER_NS_5 60 ! 1462: #define SYN_XFER_NS_6 70 ! 1463: #define SYN_XFER_NS_7 85 ! 1464: #define SYN_ULTRA_XFER_NS_0 12 ! 1465: #define SYN_ULTRA_XFER_NS_1 19 ! 1466: #define SYN_ULTRA_XFER_NS_2 25 ! 1467: #define SYN_ULTRA_XFER_NS_3 32 ! 1468: #define SYN_ULTRA_XFER_NS_4 38 ! 1469: #define SYN_ULTRA_XFER_NS_5 44 ! 1470: #define SYN_ULTRA_XFER_NS_6 50 ! 1471: #define SYN_ULTRA_XFER_NS_7 57 ! 1472: #define SYN_ULTRA_XFER_NS_8 63 ! 1473: #define SYN_ULTRA_XFER_NS_9 69 ! 1474: #define SYN_ULTRA_XFER_NS_10 75 ! 1475: #define SYN_ULTRA_XFER_NS_11 82 ! 1476: #define SYN_ULTRA_XFER_NS_12 88 ! 1477: #define SYN_ULTRA_XFER_NS_13 94 ! 1478: #define SYN_ULTRA_XFER_NS_14 100 ! 1479: #define SYN_ULTRA_XFER_NS_15 107 ! 1480: ! 1481: typedef struct ext_msg { ! 1482: uchar msg_type; ! 1483: uchar msg_len; ! 1484: uchar msg_req; ! 1485: union { ! 1486: struct { ! 1487: uchar sdtr_xfer_period; ! 1488: uchar sdtr_req_ack_offset; ! 1489: } sdtr; ! 1490: struct { ! 1491: uchar wdtr_width; ! 1492: } wdtr; ! 1493: struct { ! 1494: uchar mdp_b3; ! 1495: uchar mdp_b2; ! 1496: uchar mdp_b1; ! 1497: uchar mdp_b0; ! 1498: } mdp; ! 1499: } u_ext_msg; ! 1500: uchar res; ! 1501: } EXT_MSG; ! 1502: ! 1503: #define xfer_period u_ext_msg.sdtr.sdtr_xfer_period ! 1504: #define req_ack_offset u_ext_msg.sdtr.sdtr_req_ack_offset ! 1505: #define wdtr_width u_ext_msg.wdtr.wdtr_width ! 1506: #define mdp_b3 u_ext_msg.mdp_b3 ! 1507: #define mdp_b2 u_ext_msg.mdp_b2 ! 1508: #define mdp_b1 u_ext_msg.mdp_b1 ! 1509: #define mdp_b0 u_ext_msg.mdp_b0 ! 1510: ! 1511: typedef struct asc_dvc_cfg { ! 1512: ASC_SCSI_BIT_ID_TYPE can_tagged_qng; ! 1513: ASC_SCSI_BIT_ID_TYPE cmd_qng_enabled; ! 1514: ASC_SCSI_BIT_ID_TYPE disc_enable; ! 1515: ASC_SCSI_BIT_ID_TYPE sdtr_enable; ! 1516: uchar chip_scsi_id:4; ! 1517: uchar isa_dma_speed:4; ! 1518: uchar isa_dma_channel; ! 1519: uchar chip_version; ! 1520: ushort pci_device_id; ! 1521: ushort lib_serial_no; ! 1522: ushort lib_version; ! 1523: ushort mcode_date; ! 1524: ushort mcode_version; ! 1525: uchar max_tag_qng[ASC_MAX_TID + 1]; ! 1526: uchar *overrun_buf; ! 1527: uchar sdtr_period_offset[ASC_MAX_TID + 1]; ! 1528: ushort pci_slot_info; ! 1529: uchar adapter_info[6]; ! 1530: } ASC_DVC_CFG; ! 1531: ! 1532: #define ASC_DEF_DVC_CNTL 0xFFFF ! 1533: #define ASC_DEF_CHIP_SCSI_ID 7 ! 1534: #define ASC_DEF_ISA_DMA_SPEED 4 ! 1535: #define ASC_INIT_STATE_NULL 0x0000 ! 1536: #define ASC_INIT_STATE_BEG_GET_CFG 0x0001 ! 1537: #define ASC_INIT_STATE_END_GET_CFG 0x0002 ! 1538: #define ASC_INIT_STATE_BEG_SET_CFG 0x0004 ! 1539: #define ASC_INIT_STATE_END_SET_CFG 0x0008 ! 1540: #define ASC_INIT_STATE_BEG_LOAD_MC 0x0010 ! 1541: #define ASC_INIT_STATE_END_LOAD_MC 0x0020 ! 1542: #define ASC_INIT_STATE_BEG_INQUIRY 0x0040 ! 1543: #define ASC_INIT_STATE_END_INQUIRY 0x0080 ! 1544: #define ASC_INIT_RESET_SCSI_DONE 0x0100 ! 1545: #define ASC_INIT_STATE_WITHOUT_EEP 0x8000 ! 1546: #define ASC_PCI_DEVICE_ID_REV_A 0x1100 ! 1547: #define ASC_PCI_DEVICE_ID_REV_B 0x1200 ! 1548: #define ASC_BUG_FIX_IF_NOT_DWB 0x0001 ! 1549: #define ASC_BUG_FIX_ASYN_USE_SYN 0x0002 ! 1550: #define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41 ! 1551: #define ASC_MIN_TAGGED_CMD 7 ! 1552: #define ASC_MAX_SCSI_RESET_WAIT 30 ! 1553: ! 1554: typedef struct asc_dvc_var { ! 1555: PortAddr iop_base; ! 1556: ushort err_code; ! 1557: ushort dvc_cntl; ! 1558: ushort bug_fix_cntl; ! 1559: ushort bus_type; ! 1560: Ptr2Func isr_callback; ! 1561: Ptr2Func exe_callback; ! 1562: ASC_SCSI_BIT_ID_TYPE init_sdtr; ! 1563: ASC_SCSI_BIT_ID_TYPE sdtr_done; ! 1564: ASC_SCSI_BIT_ID_TYPE use_tagged_qng; ! 1565: ASC_SCSI_BIT_ID_TYPE unit_not_ready; ! 1566: ASC_SCSI_BIT_ID_TYPE queue_full_or_busy; ! 1567: ASC_SCSI_BIT_ID_TYPE start_motor; ! 1568: uchar scsi_reset_wait; ! 1569: uchar chip_no; ! 1570: char is_in_int; ! 1571: uchar max_total_qng; ! 1572: uchar cur_total_qng; ! 1573: uchar in_critical_cnt; ! 1574: uchar irq_no; ! 1575: uchar last_q_shortage; ! 1576: ushort init_state; ! 1577: uchar cur_dvc_qng[ASC_MAX_TID + 1]; ! 1578: uchar max_dvc_qng[ASC_MAX_TID + 1]; ! 1579: ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1]; ! 1580: ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1]; ! 1581: uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO]; ! 1582: ASC_DVC_CFG *cfg; ! 1583: Ptr2Func saved_ptr2func; ! 1584: ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always; ! 1585: char redo_scam; ! 1586: ushort res2; ! 1587: uchar dos_int13_table[ASC_MAX_TID + 1]; ! 1588: ulong max_dma_count; ! 1589: ASC_SCSI_BIT_ID_TYPE no_scam; ! 1590: ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer; ! 1591: uchar max_sdtr_index; ! 1592: uchar host_init_sdtr_index; ! 1593: ulong drv_ptr; ! 1594: ulong uc_break; ! 1595: ulong res7; ! 1596: ulong res8; ! 1597: } ASC_DVC_VAR; ! 1598: ! 1599: typedef int (* ASC_ISR_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_QDONE_INFO *); ! 1600: typedef int (* ASC_EXE_CALLBACK) (ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q *); ! 1601: ! 1602: typedef struct asc_dvc_inq_info { ! 1603: uchar type[ASC_MAX_TID + 1][ASC_MAX_LUN + 1]; ! 1604: } ASC_DVC_INQ_INFO; ! 1605: ! 1606: typedef struct asc_cap_info { ! 1607: ulong lba; ! 1608: ulong blk_size; ! 1609: } ASC_CAP_INFO; ! 1610: ! 1611: typedef struct asc_cap_info_array { ! 1612: ASC_CAP_INFO cap_info[ASC_MAX_TID + 1][ASC_MAX_LUN + 1]; ! 1613: } ASC_CAP_INFO_ARRAY; ! 1614: ! 1615: #define ASC_MCNTL_NO_SEL_TIMEOUT (ushort)0x0001 ! 1616: #define ASC_MCNTL_NULL_TARGET (ushort)0x0002 ! 1617: #define ASC_CNTL_INITIATOR (ushort)0x0001 ! 1618: #define ASC_CNTL_BIOS_GT_1GB (ushort)0x0002 ! 1619: #define ASC_CNTL_BIOS_GT_2_DISK (ushort)0x0004 ! 1620: #define ASC_CNTL_BIOS_REMOVABLE (ushort)0x0008 ! 1621: #define ASC_CNTL_NO_SCAM (ushort)0x0010 ! 1622: #define ASC_CNTL_INT_MULTI_Q (ushort)0x0080 ! 1623: #define ASC_CNTL_NO_LUN_SUPPORT (ushort)0x0040 ! 1624: #define ASC_CNTL_NO_VERIFY_COPY (ushort)0x0100 ! 1625: #define ASC_CNTL_RESET_SCSI (ushort)0x0200 ! 1626: #define ASC_CNTL_INIT_INQUIRY (ushort)0x0400 ! 1627: #define ASC_CNTL_INIT_VERBOSE (ushort)0x0800 ! 1628: #define ASC_CNTL_SCSI_PARITY (ushort)0x1000 ! 1629: #define ASC_CNTL_BURST_MODE (ushort)0x2000 ! 1630: #define ASC_CNTL_SDTR_ENABLE_ULTRA (ushort)0x4000 ! 1631: #define ASC_EEP_DVC_CFG_BEG_VL 2 ! 1632: #define ASC_EEP_MAX_DVC_ADDR_VL 15 ! 1633: #define ASC_EEP_DVC_CFG_BEG 32 ! 1634: #define ASC_EEP_MAX_DVC_ADDR 45 ! 1635: #define ASC_EEP_DEFINED_WORDS 10 ! 1636: #define ASC_EEP_MAX_ADDR 63 ! 1637: #define ASC_EEP_RES_WORDS 0 ! 1638: #define ASC_EEP_MAX_RETRY 20 ! 1639: #define ASC_MAX_INIT_BUSY_RETRY 8 ! 1640: #define ASC_EEP_ISA_PNP_WSIZE 16 ! 1641: ! 1642: typedef struct asceep_config { ! 1643: ushort cfg_lsw; ! 1644: ushort cfg_msw; ! 1645: uchar init_sdtr; ! 1646: uchar disc_enable; ! 1647: uchar use_cmd_qng; ! 1648: uchar start_motor; ! 1649: uchar max_total_qng; ! 1650: uchar max_tag_qng; ! 1651: uchar bios_scan; ! 1652: uchar power_up_wait; ! 1653: uchar no_scam; ! 1654: uchar chip_scsi_id:4; ! 1655: uchar isa_dma_speed:4; ! 1656: uchar dos_int13_table[ASC_MAX_TID + 1]; ! 1657: uchar adapter_info[6]; ! 1658: ushort cntl; ! 1659: ushort chksum; ! 1660: } ASCEEP_CONFIG; ! 1661: ! 1662: #define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800 ! 1663: #define ASC_PCI_CFG_LSW_BURST_MODE 0x0080 ! 1664: #define ASC_PCI_CFG_LSW_INTR_ABLE 0x0020 ! 1665: ! 1666: #define ASC_EEP_CMD_READ 0x80 ! 1667: #define ASC_EEP_CMD_WRITE 0x40 ! 1668: #define ASC_EEP_CMD_WRITE_ABLE 0x30 ! 1669: #define ASC_EEP_CMD_WRITE_DISABLE 0x00 ! 1670: #define ASC_OVERRUN_BSIZE 0x00000048UL ! 1671: #define ASC_CTRL_BREAK_ONCE 0x0001 ! 1672: #define ASC_CTRL_BREAK_STAY_IDLE 0x0002 ! 1673: #define ASCV_MSGOUT_BEG 0x0000 ! 1674: #define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3) ! 1675: #define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4) ! 1676: #define ASCV_BREAK_SAVED_CODE (ushort)0x0006 ! 1677: #define ASCV_MSGIN_BEG (ASCV_MSGOUT_BEG+8) ! 1678: #define ASCV_MSGIN_SDTR_PERIOD (ASCV_MSGIN_BEG+3) ! 1679: #define ASCV_MSGIN_SDTR_OFFSET (ASCV_MSGIN_BEG+4) ! 1680: #define ASCV_SDTR_DATA_BEG (ASCV_MSGIN_BEG+8) ! 1681: #define ASCV_SDTR_DONE_BEG (ASCV_SDTR_DATA_BEG+8) ! 1682: #define ASCV_MAX_DVC_QNG_BEG (ushort)0x0020 ! 1683: #define ASCV_BREAK_ADDR (ushort)0x0028 ! 1684: #define ASCV_BREAK_NOTIFY_COUNT (ushort)0x002A ! 1685: #define ASCV_BREAK_CONTROL (ushort)0x002C ! 1686: #define ASCV_BREAK_HIT_COUNT (ushort)0x002E ! 1687: ! 1688: #define ASCV_ASCDVC_ERR_CODE_W (ushort)0x0030 ! 1689: #define ASCV_MCODE_CHKSUM_W (ushort)0x0032 ! 1690: #define ASCV_MCODE_SIZE_W (ushort)0x0034 ! 1691: #define ASCV_STOP_CODE_B (ushort)0x0036 ! 1692: #define ASCV_DVC_ERR_CODE_B (ushort)0x0037 ! 1693: #define ASCV_OVERRUN_PADDR_D (ushort)0x0038 ! 1694: #define ASCV_OVERRUN_BSIZE_D (ushort)0x003C ! 1695: #define ASCV_HALTCODE_W (ushort)0x0040 ! 1696: #define ASCV_CHKSUM_W (ushort)0x0042 ! 1697: #define ASCV_MC_DATE_W (ushort)0x0044 ! 1698: #define ASCV_MC_VER_W (ushort)0x0046 ! 1699: #define ASCV_NEXTRDY_B (ushort)0x0048 ! 1700: #define ASCV_DONENEXT_B (ushort)0x0049 ! 1701: #define ASCV_USE_TAGGED_QNG_B (ushort)0x004A ! 1702: #define ASCV_SCSIBUSY_B (ushort)0x004B ! 1703: #define ASCV_Q_DONE_IN_PROGRESS_B (ushort)0x004C ! 1704: #define ASCV_CURCDB_B (ushort)0x004D ! 1705: #define ASCV_RCLUN_B (ushort)0x004E ! 1706: #define ASCV_BUSY_QHEAD_B (ushort)0x004F ! 1707: #define ASCV_DISC1_QHEAD_B (ushort)0x0050 ! 1708: #define ASCV_DISC_ENABLE_B (ushort)0x0052 ! 1709: #define ASCV_CAN_TAGGED_QNG_B (ushort)0x0053 ! 1710: #define ASCV_HOSTSCSI_ID_B (ushort)0x0055 ! 1711: #define ASCV_MCODE_CNTL_B (ushort)0x0056 ! 1712: #define ASCV_NULL_TARGET_B (ushort)0x0057 ! 1713: #define ASCV_FREE_Q_HEAD_W (ushort)0x0058 ! 1714: #define ASCV_DONE_Q_TAIL_W (ushort)0x005A ! 1715: #define ASCV_FREE_Q_HEAD_B (ushort)(ASCV_FREE_Q_HEAD_W+1) ! 1716: #define ASCV_DONE_Q_TAIL_B (ushort)(ASCV_DONE_Q_TAIL_W+1) ! 1717: #define ASCV_HOST_FLAG_B (ushort)0x005D ! 1718: #define ASCV_TOTAL_READY_Q_B (ushort)0x0064 ! 1719: #define ASCV_VER_SERIAL_B (ushort)0x0065 ! 1720: #define ASCV_HALTCODE_SAVED_W (ushort)0x0066 ! 1721: #define ASCV_WTM_FLAG_B (ushort)0x0068 ! 1722: #define ASCV_RISC_FLAG_B (ushort)0x006A ! 1723: #define ASCV_REQ_SG_LIST_QP (ushort)0x006B ! 1724: #define ASC_HOST_FLAG_IN_ISR 0x01 ! 1725: #define ASC_HOST_FLAG_ACK_INT 0x02 ! 1726: #define ASC_RISC_FLAG_GEN_INT 0x01 ! 1727: #define ASC_RISC_FLAG_REQ_SG_LIST 0x02 ! 1728: #define IOP_CTRL (0x0F) ! 1729: #define IOP_STATUS (0x0E) ! 1730: #define IOP_INT_ACK IOP_STATUS ! 1731: #define IOP_REG_IFC (0x0D) ! 1732: #define IOP_SYN_OFFSET (0x0B) ! 1733: #define IOP_EXTRA_CONTROL (0x0D) ! 1734: #define IOP_REG_PC (0x0C) ! 1735: #define IOP_RAM_ADDR (0x0A) ! 1736: #define IOP_RAM_DATA (0x08) ! 1737: #define IOP_EEP_DATA (0x06) ! 1738: #define IOP_EEP_CMD (0x07) ! 1739: #define IOP_VERSION (0x03) ! 1740: #define IOP_CONFIG_HIGH (0x04) ! 1741: #define IOP_CONFIG_LOW (0x02) ! 1742: #define IOP_SIG_BYTE (0x01) ! 1743: #define IOP_SIG_WORD (0x00) ! 1744: #define IOP_REG_DC1 (0x0E) ! 1745: #define IOP_REG_DC0 (0x0C) ! 1746: #define IOP_REG_SB (0x0B) ! 1747: #define IOP_REG_DA1 (0x0A) ! 1748: #define IOP_REG_DA0 (0x08) ! 1749: #define IOP_REG_SC (0x09) ! 1750: #define IOP_DMA_SPEED (0x07) ! 1751: #define IOP_REG_FLAG (0x07) ! 1752: #define IOP_FIFO_H (0x06) ! 1753: #define IOP_FIFO_L (0x04) ! 1754: #define IOP_REG_ID (0x05) ! 1755: #define IOP_REG_QP (0x03) ! 1756: #define IOP_REG_IH (0x02) ! 1757: #define IOP_REG_IX (0x01) ! 1758: #define IOP_REG_AX (0x00) ! 1759: #define IFC_REG_LOCK (0x00) ! 1760: #define IFC_REG_UNLOCK (0x09) ! 1761: #define IFC_WR_EN_FILTER (0x10) ! 1762: #define IFC_RD_NO_EEPROM (0x10) ! 1763: #define IFC_SLEW_RATE (0x20) ! 1764: #define IFC_ACT_NEG (0x40) ! 1765: #define IFC_INP_FILTER (0x80) ! 1766: #define IFC_INIT_DEFAULT (IFC_ACT_NEG | IFC_REG_UNLOCK) ! 1767: #define SC_SEL (uchar)(0x80) ! 1768: #define SC_BSY (uchar)(0x40) ! 1769: #define SC_ACK (uchar)(0x20) ! 1770: #define SC_REQ (uchar)(0x10) ! 1771: #define SC_ATN (uchar)(0x08) ! 1772: #define SC_IO (uchar)(0x04) ! 1773: #define SC_CD (uchar)(0x02) ! 1774: #define SC_MSG (uchar)(0x01) ! 1775: #define SEC_SCSI_CTL (uchar)(0x80) ! 1776: #define SEC_ACTIVE_NEGATE (uchar)(0x40) ! 1777: #define SEC_SLEW_RATE (uchar)(0x20) ! 1778: #define SEC_ENABLE_FILTER (uchar)(0x10) ! 1779: #define ASC_HALT_EXTMSG_IN (ushort)0x8000 ! 1780: #define ASC_HALT_CHK_CONDITION (ushort)0x8100 ! 1781: #define ASC_HALT_SS_QUEUE_FULL (ushort)0x8200 ! 1782: #define ASC_HALT_DISABLE_ASYN_USE_SYN_FIX (ushort)0x8300 ! 1783: #define ASC_HALT_ENABLE_ASYN_USE_SYN_FIX (ushort)0x8400 ! 1784: #define ASC_HALT_SDTR_REJECTED (ushort)0x4000 ! 1785: #define ASC_MAX_QNO 0xF8 ! 1786: #define ASC_DATA_SEC_BEG (ushort)0x0080 ! 1787: #define ASC_DATA_SEC_END (ushort)0x0080 ! 1788: #define ASC_CODE_SEC_BEG (ushort)0x0080 ! 1789: #define ASC_CODE_SEC_END (ushort)0x0080 ! 1790: #define ASC_QADR_BEG (0x4000) ! 1791: #define ASC_QADR_USED (ushort)(ASC_MAX_QNO * 64) ! 1792: #define ASC_QADR_END (ushort)0x7FFF ! 1793: #define ASC_QLAST_ADR (ushort)0x7FC0 ! 1794: #define ASC_QBLK_SIZE 0x40 ! 1795: #define ASC_BIOS_DATA_QBEG 0xF8 ! 1796: #define ASC_MIN_ACTIVE_QNO 0x01 ! 1797: #define ASC_QLINK_END 0xFF ! 1798: #define ASC_EEPROM_WORDS 0x10 ! 1799: #define ASC_MAX_MGS_LEN 0x10 ! 1800: #define ASC_BIOS_ADDR_DEF 0xDC00 ! 1801: #define ASC_BIOS_SIZE 0x3800 ! 1802: #define ASC_BIOS_RAM_OFF 0x3800 ! 1803: #define ASC_BIOS_RAM_SIZE 0x800 ! 1804: #define ASC_BIOS_MIN_ADDR 0xC000 ! 1805: #define ASC_BIOS_MAX_ADDR 0xEC00 ! 1806: #define ASC_BIOS_BANK_SIZE 0x0400 ! 1807: #define ASC_MCODE_START_ADDR 0x0080 ! 1808: #define ASC_CFG0_HOST_INT_ON 0x0020 ! 1809: #define ASC_CFG0_BIOS_ON 0x0040 ! 1810: #define ASC_CFG0_VERA_BURST_ON 0x0080 ! 1811: #define ASC_CFG0_SCSI_PARITY_ON 0x0800 ! 1812: #define ASC_CFG1_SCSI_TARGET_ON 0x0080 ! 1813: #define ASC_CFG1_LRAM_8BITS_ON 0x0800 ! 1814: #define ASC_CFG_MSW_CLR_MASK 0x3080 ! 1815: #define CSW_TEST1 (ASC_CS_TYPE)0x8000 ! 1816: #define CSW_AUTO_CONFIG (ASC_CS_TYPE)0x4000 ! 1817: #define CSW_RESERVED1 (ASC_CS_TYPE)0x2000 ! 1818: #define CSW_IRQ_WRITTEN (ASC_CS_TYPE)0x1000 ! 1819: #define CSW_33MHZ_SELECTED (ASC_CS_TYPE)0x0800 ! 1820: #define CSW_TEST2 (ASC_CS_TYPE)0x0400 ! 1821: #define CSW_TEST3 (ASC_CS_TYPE)0x0200 ! 1822: #define CSW_RESERVED2 (ASC_CS_TYPE)0x0100 ! 1823: #define CSW_DMA_DONE (ASC_CS_TYPE)0x0080 ! 1824: #define CSW_FIFO_RDY (ASC_CS_TYPE)0x0040 ! 1825: #define CSW_EEP_READ_DONE (ASC_CS_TYPE)0x0020 ! 1826: #define CSW_HALTED (ASC_CS_TYPE)0x0010 ! 1827: #define CSW_SCSI_RESET_ACTIVE (ASC_CS_TYPE)0x0008 ! 1828: #define CSW_PARITY_ERR (ASC_CS_TYPE)0x0004 ! 1829: #define CSW_SCSI_RESET_LATCH (ASC_CS_TYPE)0x0002 ! 1830: #define CSW_INT_PENDING (ASC_CS_TYPE)0x0001 ! 1831: #define CIW_CLR_SCSI_RESET_INT (ASC_CS_TYPE)0x1000 ! 1832: #define CIW_INT_ACK (ASC_CS_TYPE)0x0100 ! 1833: #define CIW_TEST1 (ASC_CS_TYPE)0x0200 ! 1834: #define CIW_TEST2 (ASC_CS_TYPE)0x0400 ! 1835: #define CIW_SEL_33MHZ (ASC_CS_TYPE)0x0800 ! 1836: #define CIW_IRQ_ACT (ASC_CS_TYPE)0x1000 ! 1837: #define CC_CHIP_RESET (uchar)0x80 ! 1838: #define CC_SCSI_RESET (uchar)0x40 ! 1839: #define CC_HALT (uchar)0x20 ! 1840: #define CC_SINGLE_STEP (uchar)0x10 ! 1841: #define CC_DMA_ABLE (uchar)0x08 ! 1842: #define CC_TEST (uchar)0x04 ! 1843: #define CC_BANK_ONE (uchar)0x02 ! 1844: #define CC_DIAG (uchar)0x01 ! 1845: #define ASC_1000_ID0W 0x04C1 ! 1846: #define ASC_1000_ID0W_FIX 0x00C1 ! 1847: #define ASC_1000_ID1B 0x25 ! 1848: #define ASC_EISA_BIG_IOP_GAP (0x1C30-0x0C50) ! 1849: #define ASC_EISA_SMALL_IOP_GAP (0x0020) ! 1850: #define ASC_EISA_MIN_IOP_ADDR (0x0C30) ! 1851: #define ASC_EISA_MAX_IOP_ADDR (0xFC50) ! 1852: #define ASC_EISA_REV_IOP_MASK (0x0C83) ! 1853: #define ASC_EISA_PID_IOP_MASK (0x0C80) ! 1854: #define ASC_EISA_CFG_IOP_MASK (0x0C86) ! 1855: #define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000) ! 1856: #define ASC_EISA_ID_740 0x01745004UL ! 1857: #define ASC_EISA_ID_750 0x01755004UL ! 1858: #define INS_HALTINT (ushort)0x6281 ! 1859: #define INS_HALT (ushort)0x6280 ! 1860: #define INS_SINT (ushort)0x6200 ! 1861: #define INS_RFLAG_WTM (ushort)0x7380 ! 1862: #define ASC_MC_SAVE_CODE_WSIZE 0x500 ! 1863: #define ASC_MC_SAVE_DATA_WSIZE 0x40 ! 1864: ! 1865: typedef struct asc_mc_saved { ! 1866: ushort data[ASC_MC_SAVE_DATA_WSIZE]; ! 1867: ushort code[ASC_MC_SAVE_CODE_WSIZE]; ! 1868: } ASC_MC_SAVED; ! 1869: ! 1870: #define AscGetQDoneInProgress(port) AscReadLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B) ! 1871: #define AscPutQDoneInProgress(port, val) AscWriteLramByte((port), ASCV_Q_DONE_IN_PROGRESS_B, val) ! 1872: #define AscGetVarFreeQHead(port) AscReadLramWord((port), ASCV_FREE_Q_HEAD_W) ! 1873: #define AscGetVarDoneQTail(port) AscReadLramWord((port), ASCV_DONE_Q_TAIL_W) ! 1874: #define AscPutVarFreeQHead(port, val) AscWriteLramWord((port), ASCV_FREE_Q_HEAD_W, val) ! 1875: #define AscPutVarDoneQTail(port, val) AscWriteLramWord((port), ASCV_DONE_Q_TAIL_W, val) ! 1876: #define AscGetRiscVarFreeQHead(port) AscReadLramByte((port), ASCV_NEXTRDY_B) ! 1877: #define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B) ! 1878: #define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val) ! 1879: #define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val) ! 1880: #define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data)) ; ! 1881: #define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id)) ; ! 1882: #define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data) ; ! 1883: #define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id)) ; ! 1884: #define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ]) ! 1885: #define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE) ! 1886: #define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD) ! 1887: #define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION) ! 1888: #define AscGetChipCfgLsw(port) (ushort)inpw((port)+IOP_CONFIG_LOW) ! 1889: #define AscGetChipCfgMsw(port) (ushort)inpw((port)+IOP_CONFIG_HIGH) ! 1890: #define AscSetChipCfgLsw(port, data) outpw((port)+IOP_CONFIG_LOW, data) ! 1891: #define AscSetChipCfgMsw(port, data) outpw((port)+IOP_CONFIG_HIGH, data) ! 1892: #define AscGetChipEEPCmd(port) (uchar)inp((port)+IOP_EEP_CMD) ! 1893: #define AscSetChipEEPCmd(port, data) outp((port)+IOP_EEP_CMD, data) ! 1894: #define AscGetChipEEPData(port) (ushort)inpw((port)+IOP_EEP_DATA) ! 1895: #define AscSetChipEEPData(port, data) outpw((port)+IOP_EEP_DATA, data) ! 1896: #define AscGetChipLramAddr(port) (ushort)inpw((PortAddr)((port)+IOP_RAM_ADDR)) ! 1897: #define AscSetChipLramAddr(port, addr) outpw((PortAddr)((port)+IOP_RAM_ADDR), addr) ! 1898: #define AscGetChipLramData(port) (ushort)inpw((port)+IOP_RAM_DATA) ! 1899: #define AscSetChipLramData(port, data) outpw((port)+IOP_RAM_DATA, data) ! 1900: #define AscGetChipLramDataNoSwap(port) (ushort)inpw_noswap((port)+IOP_RAM_DATA) ! 1901: #define AscSetChipLramDataNoSwap(port, data) outpw_noswap((port)+IOP_RAM_DATA, data) ! 1902: #define AscGetChipIFC(port) (uchar)inp((port)+IOP_REG_IFC) ! 1903: #define AscSetChipIFC(port, data) outp((port)+IOP_REG_IFC, data) ! 1904: #define AscGetChipStatus(port) (ASC_CS_TYPE)inpw((port)+IOP_STATUS) ! 1905: #define AscSetChipStatus(port, cs_val) outpw((port)+IOP_STATUS, cs_val) ! 1906: #define AscGetChipControl(port) (uchar)inp((port)+IOP_CTRL) ! 1907: #define AscSetChipControl(port, cc_val) outp((port)+IOP_CTRL, cc_val) ! 1908: #define AscGetChipSyn(port) (uchar)inp((port)+IOP_SYN_OFFSET) ! 1909: #define AscSetChipSyn(port, data) outp((port)+IOP_SYN_OFFSET, data) ! 1910: #define AscSetPCAddr(port, data) outpw((port)+IOP_REG_PC, data) ! 1911: #define AscGetPCAddr(port) (ushort)inpw((port)+IOP_REG_PC) ! 1912: #define AscIsIntPending(port) (AscGetChipStatus(port) & (CSW_INT_PENDING | CSW_SCSI_RESET_LATCH)) ! 1913: #define AscGetChipScsiID(port) ((AscGetChipCfgLsw(port) >> 8) & ASC_MAX_TID) ! 1914: #define AscGetExtraControl(port) (uchar)inp((port)+IOP_EXTRA_CONTROL) ! 1915: #define AscSetExtraControl(port, data) outp((port)+IOP_EXTRA_CONTROL, data) ! 1916: #define AscReadChipAX(port) (ushort)inpw((port)+IOP_REG_AX) ! 1917: #define AscWriteChipAX(port, data) outpw((port)+IOP_REG_AX, data) ! 1918: #define AscReadChipIX(port) (uchar)inp((port)+IOP_REG_IX) ! 1919: #define AscWriteChipIX(port, data) outp((port)+IOP_REG_IX, data) ! 1920: #define AscReadChipIH(port) (ushort)inpw((port)+IOP_REG_IH) ! 1921: #define AscWriteChipIH(port, data) outpw((port)+IOP_REG_IH, data) ! 1922: #define AscReadChipQP(port) (uchar)inp((port)+IOP_REG_QP) ! 1923: #define AscWriteChipQP(port, data) outp((port)+IOP_REG_QP, data) ! 1924: #define AscReadChipFIFO_L(port) (ushort)inpw((port)+IOP_REG_FIFO_L) ! 1925: #define AscWriteChipFIFO_L(port, data) outpw((port)+IOP_REG_FIFO_L, data) ! 1926: #define AscReadChipFIFO_H(port) (ushort)inpw((port)+IOP_REG_FIFO_H) ! 1927: #define AscWriteChipFIFO_H(port, data) outpw((port)+IOP_REG_FIFO_H, data) ! 1928: #define AscReadChipDmaSpeed(port) (uchar)inp((port)+IOP_DMA_SPEED) ! 1929: #define AscWriteChipDmaSpeed(port, data) outp((port)+IOP_DMA_SPEED, data) ! 1930: #define AscReadChipDA0(port) (ushort)inpw((port)+IOP_REG_DA0) ! 1931: #define AscWriteChipDA0(port) outpw((port)+IOP_REG_DA0, data) ! 1932: #define AscReadChipDA1(port) (ushort)inpw((port)+IOP_REG_DA1) ! 1933: #define AscWriteChipDA1(port) outpw((port)+IOP_REG_DA1, data) ! 1934: #define AscReadChipDC0(port) (ushort)inpw((port)+IOP_REG_DC0) ! 1935: #define AscWriteChipDC0(port) outpw((port)+IOP_REG_DC0, data) ! 1936: #define AscReadChipDC1(port) (ushort)inpw((port)+IOP_REG_DC1) ! 1937: #define AscWriteChipDC1(port) outpw((port)+IOP_REG_DC1, data) ! 1938: #define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID) ! 1939: #define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data) ! 1940: ! 1941: STATIC int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg); ! 1942: STATIC int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg); ! 1943: STATIC void AscWaitEEPRead(void); ! 1944: STATIC void AscWaitEEPWrite(void); ! 1945: STATIC ushort AscReadEEPWord(PortAddr, uchar); ! 1946: STATIC ushort AscWriteEEPWord(PortAddr, uchar, ushort); ! 1947: STATIC ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); ! 1948: STATIC int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort); ! 1949: STATIC int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); ! 1950: STATIC int AscStartChip(PortAddr); ! 1951: STATIC int AscStopChip(PortAddr); ! 1952: STATIC void AscSetChipIH(PortAddr, ushort); ! 1953: STATIC int AscIsChipHalted(PortAddr); ! 1954: STATIC void AscAckInterrupt(PortAddr); ! 1955: STATIC void AscDisableInterrupt(PortAddr); ! 1956: STATIC void AscEnableInterrupt(PortAddr); ! 1957: STATIC void AscSetBank(PortAddr, uchar); ! 1958: STATIC int AscResetChipAndScsiBus(ASC_DVC_VAR *); ! 1959: STATIC ushort AscGetIsaDmaChannel(PortAddr); ! 1960: STATIC ushort AscSetIsaDmaChannel(PortAddr, ushort); ! 1961: STATIC uchar AscSetIsaDmaSpeed(PortAddr, uchar); ! 1962: STATIC uchar AscGetIsaDmaSpeed(PortAddr); ! 1963: STATIC uchar AscReadLramByte(PortAddr, ushort); ! 1964: STATIC ushort AscReadLramWord(PortAddr, ushort); ! 1965: STATIC ulong AscReadLramDWord(PortAddr, ushort); ! 1966: STATIC void AscWriteLramWord(PortAddr, ushort, ushort); ! 1967: STATIC void AscWriteLramDWord(PortAddr, ushort, ulong); ! 1968: STATIC void AscWriteLramByte(PortAddr, ushort, uchar); ! 1969: STATIC ulong AscMemSumLramWord(PortAddr, ushort, rint); ! 1970: STATIC void AscMemWordSetLram(PortAddr, ushort, ushort, rint); ! 1971: STATIC void AscMemWordCopyToLram(PortAddr, ushort, ushort *, int); ! 1972: STATIC void AscMemDWordCopyToLram(PortAddr, ushort, ulong *, int); ! 1973: STATIC void AscMemWordCopyFromLram(PortAddr, ushort, ushort *, int); ! 1974: STATIC ushort AscInitAscDvcVar(ASC_DVC_VAR asc_ptr_type *); ! 1975: STATIC ushort AscInitFromEEP(ASC_DVC_VAR asc_ptr_type *); ! 1976: STATIC ushort AscInitFromAscDvcVar(ASC_DVC_VAR asc_ptr_type *); ! 1977: STATIC ushort AscInitMicroCodeVar(ASC_DVC_VAR asc_ptr_type * asc_dvc); ! 1978: STATIC int AscTestExternalLram(ASC_DVC_VAR asc_ptr_type *); ! 1979: STATIC uchar AscMsgOutSDTR(ASC_DVC_VAR asc_ptr_type *, uchar, uchar); ! 1980: STATIC uchar AscCalSDTRData(ASC_DVC_VAR asc_ptr_type *, uchar, uchar); ! 1981: STATIC void AscSetChipSDTR(PortAddr, uchar, uchar); ! 1982: STATIC uchar AscGetSynPeriodIndex(ASC_DVC_VAR asc_ptr_type *, ruchar); ! 1983: STATIC uchar AscAllocFreeQueue(PortAddr, uchar); ! 1984: STATIC uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar); ! 1985: STATIC int AscRiscHaltedAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong); ! 1986: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 1987: STATIC int AscRiscHaltedAbortTIX(ASC_DVC_VAR asc_ptr_type *, uchar); ! 1988: #endif /* version >= v1.3.89 */ ! 1989: STATIC int AscHostReqRiscHalt(PortAddr); ! 1990: STATIC int AscStopQueueExe(PortAddr); ! 1991: STATIC int AscStartQueueExe(PortAddr); ! 1992: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 1993: STATIC int AscCleanUpDiscQueue(PortAddr); ! 1994: #endif /* version >= v1.3.89 */ ! 1995: STATIC int AscCleanUpBusyQueue(PortAddr); ! 1996: STATIC int AscWaitTixISRDone(ASC_DVC_VAR asc_ptr_type *, uchar); ! 1997: STATIC int AscWaitISRDone(ASC_DVC_VAR asc_ptr_type *); ! 1998: STATIC ulong AscGetOnePhyAddr(ASC_DVC_VAR asc_ptr_type *, uchar *, ! 1999: ulong); ! 2000: STATIC int AscSendScsiQueue(ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 2001: ASC_SCSI_Q * scsiq, ! 2002: uchar n_q_required); ! 2003: STATIC int AscPutReadyQueue(ASC_DVC_VAR asc_ptr_type *, ! 2004: ASC_SCSI_Q *, uchar); ! 2005: STATIC int AscPutReadySgListQueue(ASC_DVC_VAR asc_ptr_type *, ! 2006: ASC_SCSI_Q *, uchar); ! 2007: STATIC int AscSetChipSynRegAtID(PortAddr, uchar, uchar); ! 2008: STATIC int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar); ! 2009: STATIC ushort AscInitLram(ASC_DVC_VAR asc_ptr_type *); ! 2010: STATIC int AscReInitLram(ASC_DVC_VAR asc_ptr_type *); ! 2011: STATIC ushort AscInitQLinkVar(ASC_DVC_VAR asc_ptr_type *); ! 2012: STATIC int AscSetLibErrorCode(ASC_DVC_VAR asc_ptr_type *, ushort); ! 2013: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 2014: STATIC int _AscWaitQDone(PortAddr, ASC_SCSI_Q *); ! 2015: #endif /* version >= v1.3.89 */ ! 2016: STATIC int AscIsrChipHalted(ASC_DVC_VAR asc_ptr_type *); ! 2017: STATIC uchar _AscCopyLramScsiDoneQ(PortAddr, ushort, ! 2018: ASC_QDONE_INFO *, ulong); ! 2019: STATIC int AscIsrQDone(ASC_DVC_VAR asc_ptr_type *); ! 2020: STATIC int AscCompareString(uchar *, uchar *, int); ! 2021: STATIC ushort AscGetEisaChipCfg(PortAddr); ! 2022: STATIC ulong AscGetEisaProductID(PortAddr); ! 2023: STATIC PortAddr AscSearchIOPortAddrEISA(PortAddr); ! 2024: STATIC uchar AscGetChipScsiCtrl(PortAddr); ! 2025: STATIC uchar AscSetChipScsiID(PortAddr, uchar); ! 2026: STATIC uchar AscGetChipVersion(PortAddr, ushort); ! 2027: STATIC ushort AscGetChipBusType(PortAddr); ! 2028: STATIC ulong AscLoadMicroCode(PortAddr, ushort, ushort *, ushort); ! 2029: STATIC int AscFindSignature(PortAddr); ! 2030: STATIC PortAddr AscSearchIOPortAddr11(PortAddr); ! 2031: STATIC void AscToggleIRQAct(PortAddr); ! 2032: STATIC void AscSetISAPNPWaitForKey(void); ! 2033: STATIC uchar AscGetChipIRQ(PortAddr, ushort); ! 2034: STATIC uchar AscSetChipIRQ(PortAddr, uchar, ushort); ! 2035: STATIC ushort AscGetChipBiosAddress(PortAddr, ushort); ! 2036: STATIC int DvcEnterCritical(void); ! 2037: STATIC void DvcLeaveCritical(int); ! 2038: STATIC void DvcInPortWords(PortAddr, ushort *, int); ! 2039: STATIC void DvcOutPortWords(PortAddr, ushort *, int); ! 2040: STATIC void DvcOutPortDWords(PortAddr, ulong *, int); ! 2041: STATIC uchar DvcReadPCIConfigByte(ASC_DVC_VAR asc_ptr_type *, ushort); ! 2042: STATIC void DvcWritePCIConfigByte(ASC_DVC_VAR asc_ptr_type *, ! 2043: ushort, uchar); ! 2044: STATIC ushort AscGetChipBiosAddress(PortAddr, ushort); ! 2045: STATIC void DvcSleepMilliSecond(ulong); ! 2046: STATIC void DvcDelayNanoSecond(ASC_DVC_VAR asc_ptr_type *, ulong); ! 2047: STATIC ulong DvcGetSGList(ASC_DVC_VAR asc_ptr_type *, uchar *, ! 2048: ulong, ASC_SG_HEAD *); ! 2049: STATIC void DvcPutScsiQ(PortAddr, ushort, ushort *, int); ! 2050: STATIC void DvcGetQinfo(PortAddr, ushort, ushort *, int); ! 2051: STATIC PortAddr AscSearchIOPortAddr(PortAddr, ushort); ! 2052: STATIC ushort AscInitGetConfig(ASC_DVC_VAR asc_ptr_type *); ! 2053: STATIC ushort AscInitSetConfig(ASC_DVC_VAR asc_ptr_type *); ! 2054: STATIC ushort AscInitAsc1000Driver(ASC_DVC_VAR asc_ptr_type *); ! 2055: STATIC void AscAsyncFix(ASC_DVC_VAR asc_ptr_type *, uchar, ! 2056: ASC_SCSI_INQUIRY *); ! 2057: STATIC int AscTagQueuingSafe(ASC_SCSI_INQUIRY *); ! 2058: STATIC void AscInquiryHandling(ASC_DVC_VAR asc_ptr_type *, ! 2059: uchar, ASC_SCSI_INQUIRY *); ! 2060: STATIC int AscExeScsiQueue(ASC_DVC_VAR asc_ptr_type *, ASC_SCSI_Q *); ! 2061: STATIC int AscISR(ASC_DVC_VAR asc_ptr_type *); ! 2062: STATIC uint AscGetNumOfFreeQueue(ASC_DVC_VAR asc_ptr_type *, uchar, ! 2063: uchar); ! 2064: STATIC int AscSgListToQueue(int); ! 2065: STATIC int AscAbortSRB(ASC_DVC_VAR asc_ptr_type *, ulong); ! 2066: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 2067: STATIC int AscResetDevice(ASC_DVC_VAR asc_ptr_type *, uchar); ! 2068: #endif /* version >= v1.3.89 */ ! 2069: STATIC int AscResetSB(ASC_DVC_VAR asc_ptr_type *); ! 2070: STATIC void AscEnableIsaDma(uchar); ! 2071: STATIC ulong AscGetMaxDmaCount(ushort); ! 2072: ! 2073: ! 2074: /* ! 2075: * --- Adv Library Constants and Macros ! 2076: */ ! 2077: ! 2078: #define ADV_LIB_VERSION_MAJOR 3 ! 2079: #define ADV_LIB_VERSION_MINOR 45 ! 2080: ! 2081: /* d_os_dep.h */ ! 2082: #define ADV_OS_LINUX ! 2083: ! 2084: /* ! 2085: * Define Adv Library required special types. ! 2086: */ ! 2087: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0) ! 2088: #define AdvPortAddr unsigned short /* I/O Port address size */ ! 2089: #else /* version >= v1,3,0 */ ! 2090: #define AdvPortAddr unsigned long /* Virtual memory address size */ ! 2091: #endif /* version >= v1,3,0 */ ! 2092: ! 2093: /* ! 2094: * Define Adv Library required memory access macros. ! 2095: */ ! 2096: #define ADV_MEM_READB(addr) readb(addr) ! 2097: #define ADV_MEM_READW(addr) readw(addr) ! 2098: #define ADV_MEM_WRITEB(addr, byte) writeb(byte, addr) ! 2099: #define ADV_MEM_WRITEW(addr, word) writew(word, addr) ! 2100: ! 2101: /* ! 2102: * The I/O memory mapping function names changed in 2.1.X. ! 2103: */ ! 2104: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0) ! 2105: #define ioremap vremap ! 2106: #define iounmap vfree ! 2107: #endif /* version < v2.1.0 */ ! 2108: ! 2109: /* ! 2110: * Define total number of simultaneous maximum element scatter-gather ! 2111: * requests, i.e. ADV_TOT_SG_LIST * ADV_MAX_SG_LIST is the total number ! 2112: * of simultaneous scatter-gather elements supported per wide adapter. ! 2113: */ ! 2114: #define ADV_TOT_SG_LIST 64 ! 2115: ! 2116: /* ! 2117: * Define Adv Library required per request scatter-gather element limit. ! 2118: */ ! 2119: #define ADV_MAX_SG_LIST 64 ! 2120: ! 2121: /* ! 2122: * Scatter-Gather Definitions per request. ! 2123: * ! 2124: * Because SG block memory is allocated in virtual memory but is ! 2125: * referenced by the microcode as physical memory, we need to do ! 2126: * calculations to insure there will be enough physically contiguous ! 2127: * memory to support ADV_MAX_SG_LIST SG entries. ! 2128: */ ! 2129: ! 2130: /* Number of SG blocks needed. */ ! 2131: #define ADV_NUM_SG_BLOCK \ ! 2132: ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK) ! 2133: ! 2134: /* Total contiguous memory needed for SG blocks. */ ! 2135: #define ADV_SG_TOTAL_MEM_SIZE \ ! 2136: (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK) ! 2137: ! 2138: #define ASC_PAGE_SIZE PAGE_SIZE ! 2139: ! 2140: /* ! 2141: * Number of page crossings possible for the total contiguous virtual memory ! 2142: * needed for SG blocks. ! 2143: * ! 2144: * We need to allocate this many additional SG blocks in virtual memory to ! 2145: * insure there will be space for ADV_NUM_SG_BLOCK physically contiguous ! 2146: * scatter-gather blocks. ! 2147: */ ! 2148: #define ADV_NUM_PAGE_CROSSING \ ! 2149: ((ADV_SG_TOTAL_MEM_SIZE + (ASC_PAGE_SIZE - 1))/ASC_PAGE_SIZE) ! 2150: ! 2151: /* ! 2152: * Define Adv Library Assertion Macro. ! 2153: */ ! 2154: ! 2155: #define ADV_ASSERT(a) ASC_ASSERT(a) ! 2156: ! 2157: /* a_condor.h */ ! 2158: #define ADV_PCI_VENDOR_ID 0x10CD ! 2159: #define ADV_PCI_DEVICE_ID_REV_A 0x2300 ! 2160: ! 2161: #define ASC_EEP_DVC_CFG_BEGIN (0x00) ! 2162: #define ASC_EEP_DVC_CFG_END (0x15) ! 2163: #define ASC_EEP_DVC_CTL_BEGIN (0x16) /* location of OEM name */ ! 2164: #define ASC_EEP_MAX_WORD_ADDR (0x1E) ! 2165: ! 2166: #define ASC_EEP_DELAY_MS 100 ! 2167: ! 2168: /* ! 2169: * EEPROM bits reference by the RISC after initialization. ! 2170: */ ! 2171: #define ADV_EEPROM_BIG_ENDIAN 0x8000 /* EEPROM Bit 15 */ ! 2172: #define ADV_EEPROM_BIOS_ENABLE 0x4000 /* EEPROM Bit 14 */ ! 2173: #define ADV_EEPROM_TERM_POL 0x2000 /* EEPROM Bit 13 */ ! 2174: ! 2175: /* ! 2176: * EEPROM configuration format ! 2177: * ! 2178: * Field naming convention: ! 2179: * ! 2180: * *_enable indicates the field enables or disables the feature. The ! 2181: * value is never reset. ! 2182: * ! 2183: * *_able indicates both whether a feature should be enabled or disabled ! 2184: * and whether a device isi capable of the feature. At initialization ! 2185: * this field may be set, but later if a device is found to be incapable ! 2186: * of the feature, the field is cleared. ! 2187: * ! 2188: * Default values are maintained in a_init.c in the structure ! 2189: * Default_EEPROM_Config. ! 2190: */ ! 2191: typedef struct adveep_config ! 2192: { ! 2193: /* Word Offset, Description */ ! 2194: ! 2195: ushort cfg_lsw; /* 00 power up initialization */ ! 2196: /* bit 13 set - Term Polarity Control */ ! 2197: /* bit 14 set - BIOS Enable */ ! 2198: /* bit 15 set - Big Endian Mode */ ! 2199: ushort cfg_msw; /* 01 unused */ ! 2200: ushort disc_enable; /* 02 disconnect enable */ ! 2201: ushort wdtr_able; /* 03 Wide DTR able */ ! 2202: ushort sdtr_able; /* 04 Synchronous DTR able */ ! 2203: ushort start_motor; /* 05 send start up motor */ ! 2204: ushort tagqng_able; /* 06 tag queuing able */ ! 2205: ushort bios_scan; /* 07 BIOS device control */ ! 2206: ushort scam_tolerant; /* 08 no scam */ ! 2207: ! 2208: uchar adapter_scsi_id; /* 09 Host Adapter ID */ ! 2209: uchar bios_boot_delay; /* power up wait */ ! 2210: ! 2211: uchar scsi_reset_delay; /* 10 reset delay */ ! 2212: uchar bios_id_lun; /* first boot device scsi id & lun */ ! 2213: /* high nibble is lun */ ! 2214: /* low nibble is scsi id */ ! 2215: ! 2216: uchar termination; /* 11 0 - automatic */ ! 2217: /* 1 - low off / high off */ ! 2218: /* 2 - low off / high on */ ! 2219: /* 3 - low on / high on */ ! 2220: /* There is no low on / high off */ ! 2221: ! 2222: uchar reserved1; /* reserved byte (not used) */ ! 2223: ! 2224: ushort bios_ctrl; /* 12 BIOS control bits */ ! 2225: /* bit 0 set: BIOS don't act as initiator. */ ! 2226: /* bit 1 set: BIOS > 1 GB support */ ! 2227: /* bit 2 set: BIOS > 2 Disk Support */ ! 2228: /* bit 3 set: BIOS don't support removables */ ! 2229: /* bit 4 set: BIOS support bootable CD */ ! 2230: /* bit 5 set: */ ! 2231: /* bit 6 set: BIOS support multiple LUNs */ ! 2232: /* bit 7 set: BIOS display of message */ ! 2233: /* bit 8 set: */ ! 2234: /* bit 9 set: Reset SCSI bus during init. */ ! 2235: /* bit 10 set: */ ! 2236: /* bit 11 set: No verbose initialization. */ ! 2237: /* bit 12 set: SCSI parity enabled */ ! 2238: /* bit 13 set: */ ! 2239: /* bit 14 set: */ ! 2240: /* bit 15 set: */ ! 2241: ushort ultra_able; /* 13 ULTRA speed able */ ! 2242: ushort reserved2; /* 14 reserved */ ! 2243: uchar max_host_qng; /* 15 maximum host queuing */ ! 2244: uchar max_dvc_qng; /* maximum per device queuing */ ! 2245: ushort dvc_cntl; /* 16 control bit for driver */ ! 2246: ushort bug_fix; /* 17 control bit for bug fix */ ! 2247: ushort serial_number_word1; /* 18 Board serial number word 1 */ ! 2248: ushort serial_number_word2; /* 19 Board serial number word 2 */ ! 2249: ushort serial_number_word3; /* 20 Board serial number word 3 */ ! 2250: ushort check_sum; /* 21 EEP check sum */ ! 2251: uchar oem_name[16]; /* 22 OEM name */ ! 2252: ushort dvc_err_code; /* 30 last device driver error code */ ! 2253: ushort adv_err_code; /* 31 last uc and Adv Lib error code */ ! 2254: ushort adv_err_addr; /* 32 last uc error address */ ! 2255: ushort saved_dvc_err_code; /* 33 saved last dev. driver error code */ ! 2256: ushort saved_adv_err_code; /* 34 saved last uc and Adv Lib error code */ ! 2257: ushort saved_adv_err_addr; /* 35 saved last uc error address */ ! 2258: ushort num_of_err; /* 36 number of error */ ! 2259: } ADVEEP_CONFIG; ! 2260: ! 2261: /* ! 2262: * EEPROM Commands ! 2263: */ ! 2264: #define ASC_EEP_CMD_DONE 0x0200 ! 2265: #define ASC_EEP_CMD_DONE_ERR 0x0001 ! 2266: ! 2267: /* cfg_word */ ! 2268: #define EEP_CFG_WORD_BIG_ENDIAN 0x8000 ! 2269: ! 2270: /* bios_ctrl */ ! 2271: #define BIOS_CTRL_BIOS 0x0001 ! 2272: #define BIOS_CTRL_EXTENDED_XLAT 0x0002 ! 2273: #define BIOS_CTRL_GT_2_DISK 0x0004 ! 2274: #define BIOS_CTRL_BIOS_REMOVABLE 0x0008 ! 2275: #define BIOS_CTRL_BOOTABLE_CD 0x0010 ! 2276: #define BIOS_CTRL_MULTIPLE_LUN 0x0040 ! 2277: #define BIOS_CTRL_DISPLAY_MSG 0x0080 ! 2278: #define BIOS_CTRL_NO_SCAM 0x0100 ! 2279: #define BIOS_CTRL_RESET_SCSI_BUS 0x0200 ! 2280: #define BIOS_CTRL_INIT_VERBOSE 0x0800 ! 2281: #define BIOS_CTRL_SCSI_PARITY 0x1000 ! 2282: ! 2283: /* ! 2284: * ASC 3550 Internal Memory Size - 8KB ! 2285: */ ! 2286: #define ADV_CONDOR_MEMSIZE 0x2000 /* 8 KB Internal Memory */ ! 2287: ! 2288: /* ! 2289: * ASC 3550 I/O Length - 64 bytes ! 2290: */ ! 2291: #define ADV_CONDOR_IOLEN 0x40 /* I/O Port Range in bytes */ ! 2292: ! 2293: /* ! 2294: * Byte I/O register address from base of 'iop_base'. ! 2295: */ ! 2296: #define IOPB_INTR_STATUS_REG 0x00 ! 2297: #define IOPB_CHIP_ID_1 0x01 ! 2298: #define IOPB_INTR_ENABLES 0x02 ! 2299: #define IOPB_CHIP_TYPE_REV 0x03 ! 2300: #define IOPB_RES_ADDR_4 0x04 ! 2301: #define IOPB_RES_ADDR_5 0x05 ! 2302: #define IOPB_RAM_DATA 0x06 ! 2303: #define IOPB_RES_ADDR_7 0x07 ! 2304: #define IOPB_FLAG_REG 0x08 ! 2305: #define IOPB_RES_ADDR_9 0x09 ! 2306: #define IOPB_RISC_CSR 0x0A ! 2307: #define IOPB_RES_ADDR_B 0x0B ! 2308: #define IOPB_RES_ADDR_C 0x0C ! 2309: #define IOPB_RES_ADDR_D 0x0D ! 2310: #define IOPB_RES_ADDR_E 0x0E ! 2311: #define IOPB_RES_ADDR_F 0x0F ! 2312: #define IOPB_MEM_CFG 0x10 ! 2313: #define IOPB_RES_ADDR_11 0x11 ! 2314: #define IOPB_RES_ADDR_12 0x12 ! 2315: #define IOPB_RES_ADDR_13 0x13 ! 2316: #define IOPB_FLASH_PAGE 0x14 ! 2317: #define IOPB_RES_ADDR_15 0x15 ! 2318: #define IOPB_RES_ADDR_16 0x16 ! 2319: #define IOPB_RES_ADDR_17 0x17 ! 2320: #define IOPB_FLASH_DATA 0x18 ! 2321: #define IOPB_RES_ADDR_19 0x19 ! 2322: #define IOPB_RES_ADDR_1A 0x1A ! 2323: #define IOPB_RES_ADDR_1B 0x1B ! 2324: #define IOPB_RES_ADDR_1C 0x1C ! 2325: #define IOPB_RES_ADDR_1D 0x1D ! 2326: #define IOPB_RES_ADDR_1E 0x1E ! 2327: #define IOPB_RES_ADDR_1F 0x1F ! 2328: #define IOPB_DMA_CFG0 0x20 ! 2329: #define IOPB_DMA_CFG1 0x21 ! 2330: #define IOPB_TICKLE 0x22 ! 2331: #define IOPB_DMA_REG_WR 0x23 ! 2332: #define IOPB_SDMA_STATUS 0x24 ! 2333: #define IOPB_SCSI_BYTE_CNT 0x25 ! 2334: #define IOPB_HOST_BYTE_CNT 0x26 ! 2335: #define IOPB_BYTE_LEFT_TO_XFER 0x27 ! 2336: #define IOPB_BYTE_TO_XFER_0 0x28 ! 2337: #define IOPB_BYTE_TO_XFER_1 0x29 ! 2338: #define IOPB_BYTE_TO_XFER_2 0x2A ! 2339: #define IOPB_BYTE_TO_XFER_3 0x2B ! 2340: #define IOPB_ACC_GRP 0x2C ! 2341: #define IOPB_RES_ADDR_2D 0x2D ! 2342: #define IOPB_DEV_ID 0x2E ! 2343: #define IOPB_RES_ADDR_2F 0x2F ! 2344: #define IOPB_SCSI_DATA 0x30 ! 2345: #define IOPB_RES_ADDR_31 0x31 ! 2346: #define IOPB_RES_ADDR_32 0x32 ! 2347: #define IOPB_SCSI_DATA_HSHK 0x33 ! 2348: #define IOPB_SCSI_CTRL 0x34 ! 2349: #define IOPB_RES_ADDR_35 0x35 ! 2350: #define IOPB_RES_ADDR_36 0x36 ! 2351: #define IOPB_RES_ADDR_37 0x37 ! 2352: #define IOPB_RES_ADDR_38 0x38 ! 2353: #define IOPB_RES_ADDR_39 0x39 ! 2354: #define IOPB_RES_ADDR_3A 0x3A ! 2355: #define IOPB_RES_ADDR_3B 0x3B ! 2356: #define IOPB_RFIFO_CNT 0x3C ! 2357: #define IOPB_RES_ADDR_3D 0x3D ! 2358: #define IOPB_RES_ADDR_3E 0x3E ! 2359: #define IOPB_RES_ADDR_3F 0x3F ! 2360: ! 2361: /* ! 2362: * Word I/O register address from base of 'iop_base'. ! 2363: */ ! 2364: #define IOPW_CHIP_ID_0 0x00 /* CID0 */ ! 2365: #define IOPW_CTRL_REG 0x02 /* CC */ ! 2366: #define IOPW_RAM_ADDR 0x04 /* LA */ ! 2367: #define IOPW_RAM_DATA 0x06 /* LD */ ! 2368: #define IOPW_RES_ADDR_08 0x08 ! 2369: #define IOPW_RISC_CSR 0x0A /* CSR */ ! 2370: #define IOPW_SCSI_CFG0 0x0C /* CFG0 */ ! 2371: #define IOPW_SCSI_CFG1 0x0E /* CFG1 */ ! 2372: #define IOPW_RES_ADDR_10 0x10 ! 2373: #define IOPW_SEL_MASK 0x12 /* SM */ ! 2374: #define IOPW_RES_ADDR_14 0x14 ! 2375: #define IOPW_FLASH_ADDR 0x16 /* FA */ ! 2376: #define IOPW_RES_ADDR_18 0x18 ! 2377: #define IOPW_EE_CMD 0x1A /* EC */ ! 2378: #define IOPW_EE_DATA 0x1C /* ED */ ! 2379: #define IOPW_SFIFO_CNT 0x1E /* SFC */ ! 2380: #define IOPW_RES_ADDR_20 0x20 ! 2381: #define IOPW_Q_BASE 0x22 /* QB */ ! 2382: #define IOPW_QP 0x24 /* QP */ ! 2383: #define IOPW_IX 0x26 /* IX */ ! 2384: #define IOPW_SP 0x28 /* SP */ ! 2385: #define IOPW_PC 0x2A /* PC */ ! 2386: #define IOPW_RES_ADDR_2C 0x2C ! 2387: #define IOPW_RES_ADDR_2E 0x2E ! 2388: #define IOPW_SCSI_DATA 0x30 /* SD */ ! 2389: #define IOPW_SCSI_DATA_HSHK 0x32 /* SDH */ ! 2390: #define IOPW_SCSI_CTRL 0x34 /* SC */ ! 2391: #define IOPW_HSHK_CFG 0x36 /* HCFG */ ! 2392: #define IOPW_SXFR_STATUS 0x36 /* SXS */ ! 2393: #define IOPW_SXFR_CNTL 0x38 /* SXL */ ! 2394: #define IOPW_SXFR_CNTH 0x3A /* SXH */ ! 2395: #define IOPW_RES_ADDR_3C 0x3C ! 2396: #define IOPW_RFIFO_DATA 0x3E /* RFD */ ! 2397: ! 2398: /* ! 2399: * Doubleword I/O register address from base of 'iop_base'. ! 2400: */ ! 2401: #define IOPDW_RES_ADDR_0 0x00 ! 2402: #define IOPDW_RAM_DATA 0x04 ! 2403: #define IOPDW_RES_ADDR_8 0x08 ! 2404: #define IOPDW_RES_ADDR_C 0x0C ! 2405: #define IOPDW_RES_ADDR_10 0x10 ! 2406: #define IOPDW_RES_ADDR_14 0x14 ! 2407: #define IOPDW_RES_ADDR_18 0x18 ! 2408: #define IOPDW_RES_ADDR_1C 0x1C ! 2409: #define IOPDW_SDMA_ADDR0 0x20 ! 2410: #define IOPDW_SDMA_ADDR1 0x24 ! 2411: #define IOPDW_SDMA_COUNT 0x28 ! 2412: #define IOPDW_SDMA_ERROR 0x2C ! 2413: #define IOPDW_RDMA_ADDR0 0x30 ! 2414: #define IOPDW_RDMA_ADDR1 0x34 ! 2415: #define IOPDW_RDMA_COUNT 0x38 ! 2416: #define IOPDW_RDMA_ERROR 0x3C ! 2417: ! 2418: #define ADV_CHIP_ID_BYTE 0x25 ! 2419: #define ADV_CHIP_ID_WORD 0x04C1 ! 2420: ! 2421: #define ADV_SC_SCSI_BUS_RESET 0x2000 ! 2422: ! 2423: #define ADV_INTR_ENABLE_HOST_INTR 0x01 ! 2424: #define ADV_INTR_ENABLE_SEL_INTR 0x02 ! 2425: #define ADV_INTR_ENABLE_DPR_INTR 0x04 ! 2426: #define ADV_INTR_ENABLE_RTA_INTR 0x08 ! 2427: #define ADV_INTR_ENABLE_RMA_INTR 0x10 ! 2428: #define ADV_INTR_ENABLE_RST_INTR 0x20 ! 2429: #define ADV_INTR_ENABLE_DPE_INTR 0x40 ! 2430: #define ADV_INTR_ENABLE_GLOBAL_INTR 0x80 ! 2431: ! 2432: #define ADV_INTR_STATUS_INTRA 0x01 ! 2433: #define ADV_INTR_STATUS_INTRB 0x02 ! 2434: #define ADV_INTR_STATUS_INTRC 0x04 ! 2435: ! 2436: #define ADV_RISC_CSR_STOP (0x0000) ! 2437: #define ADV_RISC_TEST_COND (0x2000) ! 2438: #define ADV_RISC_CSR_RUN (0x4000) ! 2439: #define ADV_RISC_CSR_SINGLE_STEP (0x8000) ! 2440: ! 2441: #define ADV_CTRL_REG_HOST_INTR 0x0100 ! 2442: #define ADV_CTRL_REG_SEL_INTR 0x0200 ! 2443: #define ADV_CTRL_REG_DPR_INTR 0x0400 ! 2444: #define ADV_CTRL_REG_RTA_INTR 0x0800 ! 2445: #define ADV_CTRL_REG_RMA_INTR 0x1000 ! 2446: #define ADV_CTRL_REG_RES_BIT14 0x2000 ! 2447: #define ADV_CTRL_REG_DPE_INTR 0x4000 ! 2448: #define ADV_CTRL_REG_POWER_DONE 0x8000 ! 2449: #define ADV_CTRL_REG_ANY_INTR 0xFF00 ! 2450: ! 2451: #define ADV_CTRL_REG_CMD_RESET 0x00C6 ! 2452: #define ADV_CTRL_REG_CMD_WR_IO_REG 0x00C5 ! 2453: #define ADV_CTRL_REG_CMD_RD_IO_REG 0x00C4 ! 2454: #define ADV_CTRL_REG_CMD_WR_PCI_CFG_SPACE 0x00C3 ! 2455: #define ADV_CTRL_REG_CMD_RD_PCI_CFG_SPACE 0x00C2 ! 2456: ! 2457: #define ADV_SCSI_CTRL_RSTOUT 0x2000 ! 2458: ! 2459: #define AdvIsIntPending(port) \ ! 2460: (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR) ! 2461: ! 2462: /* ! 2463: * SCSI_CFG0 Register bit definitions ! 2464: */ ! 2465: #define TIMER_MODEAB 0xC000 /* Watchdog, Second, and Select. Timer Ctrl. */ ! 2466: #define PARITY_EN 0x2000 /* Enable SCSI Parity Error detection */ ! 2467: #define EVEN_PARITY 0x1000 /* Select Even Parity */ ! 2468: #define WD_LONG 0x0800 /* Watchdog Interval, 1: 57 min, 0: 13 sec */ ! 2469: #define QUEUE_128 0x0400 /* Queue Size, 1: 128 byte, 0: 64 byte */ ! 2470: #define PRIM_MODE 0x0100 /* Primitive SCSI mode */ ! 2471: #define SCAM_EN 0x0080 /* Enable SCAM selection */ ! 2472: #define SEL_TMO_LONG 0x0040 /* Sel/Resel Timeout, 1: 400 ms, 0: 1.6 ms */ ! 2473: #define CFRM_ID 0x0020 /* SCAM id sel. confirm., 1: fast, 0: 6.4 ms */ ! 2474: #define OUR_ID_EN 0x0010 /* Enable OUR_ID bits */ ! 2475: #define OUR_ID 0x000F /* SCSI ID */ ! 2476: ! 2477: /* ! 2478: * SCSI_CFG1 Register bit definitions ! 2479: */ ! 2480: #define BIG_ENDIAN 0x8000 /* Enable Big Endian Mode MIO:15, EEP:15 */ ! 2481: #define TERM_POL 0x2000 /* Terminator Polarity Ctrl. MIO:13, EEP:13 */ ! 2482: #define SLEW_RATE 0x1000 /* SCSI output buffer slew rate */ ! 2483: #define FILTER_SEL 0x0C00 /* Filter Period Selection */ ! 2484: #define FLTR_DISABLE 0x0000 /* Input Filtering Disabled */ ! 2485: #define FLTR_11_TO_20NS 0x0800 /* Input Filtering 11ns to 20ns */ ! 2486: #define FLTR_21_TO_39NS 0x0C00 /* Input Filtering 21ns to 39ns */ ! 2487: #define ACTIVE_DBL 0x0200 /* Disable Active Negation */ ! 2488: #define DIFF_MODE 0x0100 /* SCSI differential Mode (Read-Only) */ ! 2489: #define DIFF_SENSE 0x0080 /* 1: No SE cables, 0: SE cable (Read-Only) */ ! 2490: #define TERM_CTL_SEL 0x0040 /* Enable TERM_CTL_H and TERM_CTL_L */ ! 2491: #define TERM_CTL 0x0030 /* External SCSI Termination Bits */ ! 2492: #define TERM_CTL_H 0x0020 /* Enable External SCSI Upper Termination */ ! 2493: #define TERM_CTL_L 0x0010 /* Enable External SCSI Lower Termination */ ! 2494: #define CABLE_DETECT 0x000F /* External SCSI Cable Connection Status */ ! 2495: ! 2496: #define CABLE_ILLEGAL_A 0x7 ! 2497: /* x 0 0 0 | on on | Illegal (all 3 connectors are used) */ ! 2498: ! 2499: #define CABLE_ILLEGAL_B 0xB ! 2500: /* 0 x 0 0 | on on | Illegal (all 3 connectors are used) */ ! 2501: ! 2502: /* ! 2503: The following table details the SCSI_CFG1 Termination Polarity, ! 2504: Termination Control and Cable Detect bits. ! 2505: ! 2506: Cable Detect | Termination ! 2507: Bit 3 2 1 0 | 5 4 | Notes ! 2508: _____________|________|____________________ ! 2509: 1 1 1 0 | on on | Internal wide only ! 2510: 1 1 0 1 | on on | Internal narrow only ! 2511: 1 0 1 1 | on on | External narrow only ! 2512: 0 x 1 1 | on on | External wide only ! 2513: 1 1 0 0 | on off| Internal wide and internal narrow ! 2514: 1 0 1 0 | on off| Internal wide and external narrow ! 2515: 0 x 1 0 | off off| Internal wide and external wide ! 2516: 1 0 0 1 | on off| Internal narrow and external narrow ! 2517: 0 x 0 1 | on off| Internal narrow and external wide ! 2518: 1 1 1 1 | on on | No devices are attached ! 2519: x 0 0 0 | on on | Illegal (all 3 connectors are used) ! 2520: 0 x 0 0 | on on | Illegal (all 3 connectors are used) ! 2521: ! 2522: x means don't-care (either '0' or '1') ! 2523: ! 2524: If term_pol (bit 13) is '0' (active-low terminator enable), then: ! 2525: 'on' is '0' and 'off' is '1'. ! 2526: ! 2527: If term_pol bit is '1' (meaning active-hi terminator enable), then: ! 2528: 'on' is '1' and 'off' is '0'. ! 2529: */ ! 2530: ! 2531: /* ! 2532: * MEM_CFG Register bit definitions ! 2533: */ ! 2534: #define BIOS_EN 0x40 /* BIOS Enable MIO:14,EEP:14 */ ! 2535: #define FAST_EE_CLK 0x20 /* Diagnostic Bit */ ! 2536: #define RAM_SZ 0x1C /* Specify size of RAM to RISC */ ! 2537: #define RAM_SZ_2KB 0x00 /* 2 KB */ ! 2538: #define RAM_SZ_4KB 0x04 /* 4 KB */ ! 2539: #define RAM_SZ_8KB 0x08 /* 8 KB */ ! 2540: #define RAM_SZ_16KB 0x0C /* 16 KB */ ! 2541: #define RAM_SZ_32KB 0x10 /* 32 KB */ ! 2542: #define RAM_SZ_64KB 0x14 /* 64 KB */ ! 2543: ! 2544: /* ! 2545: * DMA_CFG0 Register bit definitions ! 2546: * ! 2547: * This register is only accessible to the host. ! 2548: */ ! 2549: #define BC_THRESH_ENB 0x80 /* PCI DMA Start Conditions */ ! 2550: #define FIFO_THRESH 0x70 /* PCI DMA FIFO Threshold */ ! 2551: #define FIFO_THRESH_16B 0x00 /* 16 bytes */ ! 2552: #define FIFO_THRESH_32B 0x20 /* 32 bytes */ ! 2553: #define FIFO_THRESH_48B 0x30 /* 48 bytes */ ! 2554: #define FIFO_THRESH_64B 0x40 /* 64 bytes */ ! 2555: #define FIFO_THRESH_80B 0x50 /* 80 bytes (default) */ ! 2556: #define FIFO_THRESH_96B 0x60 /* 96 bytes */ ! 2557: #define FIFO_THRESH_112B 0x70 /* 112 bytes */ ! 2558: #define START_CTL 0x0C /* DMA start conditions */ ! 2559: #define START_CTL_TH 0x00 /* Wait threshold level (default) */ ! 2560: #define START_CTL_ID 0x04 /* Wait SDMA/SBUS idle */ ! 2561: #define START_CTL_THID 0x08 /* Wait threshold and SDMA/SBUS idle */ ! 2562: #define START_CTL_EMFU 0x0C /* Wait SDMA FIFO empty/full */ ! 2563: #define READ_CMD 0x03 /* Memory Read Method */ ! 2564: #define READ_CMD_MR 0x00 /* Memory Read */ ! 2565: #define READ_CMD_MRL 0x02 /* Memory Read Long */ ! 2566: #define READ_CMD_MRM 0x03 /* Memory Read Multiple (default) */ ! 2567: ! 2568: /* a_advlib.h */ ! 2569: ! 2570: /* ! 2571: * Adv Library Status Definitions ! 2572: */ ! 2573: #define ADV_TRUE 1 ! 2574: #define ADV_FALSE 0 ! 2575: #define ADV_NOERROR 1 ! 2576: #define ADV_SUCCESS 1 ! 2577: #define ADV_BUSY 0 ! 2578: #define ADV_ERROR (-1) ! 2579: ! 2580: ! 2581: /* ! 2582: * ASC_DVC_VAR 'warn_code' values ! 2583: */ ! 2584: #define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */ ! 2585: #define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */ ! 2586: #define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */ ! 2587: #define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */ ! 2588: ! 2589: #define ADV_MAX_TID 15 /* max. target identifier */ ! 2590: #define ADV_MAX_LUN 7 /* max. logical unit number */ ! 2591: ! 2592: ! 2593: /* ! 2594: * AscInitGetConfig() and AscInitAsc1000Driver() Definitions ! 2595: * ! 2596: * Error code values are set in ASC_DVC_VAR 'err_code'. ! 2597: */ ! 2598: #define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */ ! 2599: #define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */ ! 2600: #define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */ ! 2601: #define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */ ! 2602: #define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */ ! 2603: #define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */ ! 2604: #define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */ ! 2605: #define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */ ! 2606: #define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */ ! 2607: #define ASC_IERR_RW_LRAM 0x8000 /* read/write local RAM error */ ! 2608: ! 2609: /* ! 2610: * Fixed locations of microcode operating variables. ! 2611: */ ! 2612: #define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */ ! 2613: #define ASC_MC_CODE_END_ADDR 0x002A /* microcode end address */ ! 2614: #define ASC_MC_CODE_CHK_SUM 0x002C /* microcode code checksum */ ! 2615: #define ASC_MC_STACK_BEGIN 0x002E /* microcode stack begin */ ! 2616: #define ASC_MC_STACK_END 0x0030 /* microcode stack end */ ! 2617: #define ASC_MC_VERSION_DATE 0x0038 /* microcode version */ ! 2618: #define ASC_MC_VERSION_NUM 0x003A /* microcode number */ ! 2619: #define ASCV_VER_SERIAL_W 0x003C /* used in dos_init */ ! 2620: #define ASC_MC_BIOSMEM 0x0040 /* BIOS RISC Memory Start */ ! 2621: #define ASC_MC_BIOSLEN 0x0050 /* BIOS RISC Memory Length */ ! 2622: #define ASC_MC_HALTCODE 0x0094 /* microcode halt code */ ! 2623: #define ASC_MC_CALLERPC 0x0096 /* microcode halt caller PC */ ! 2624: #define ASC_MC_ADAPTER_SCSI_ID 0x0098 /* one ID byte + reserved */ ! 2625: #define ASC_MC_ULTRA_ABLE 0x009C ! 2626: #define ASC_MC_SDTR_ABLE 0x009E ! 2627: #define ASC_MC_TAGQNG_ABLE 0x00A0 ! 2628: #define ASC_MC_DISC_ENABLE 0x00A2 ! 2629: #define ASC_MC_IDLE_CMD 0x00A6 ! 2630: #define ASC_MC_IDLE_PARA_STAT 0x00A8 ! 2631: #define ASC_MC_DEFAULT_SCSI_CFG0 0x00AC ! 2632: #define ASC_MC_DEFAULT_SCSI_CFG1 0x00AE ! 2633: #define ASC_MC_DEFAULT_MEM_CFG 0x00B0 ! 2634: #define ASC_MC_DEFAULT_SEL_MASK 0x00B2 ! 2635: #define ASC_MC_RISC_NEXT_READY 0x00B4 ! 2636: #define ASC_MC_RISC_NEXT_DONE 0x00B5 ! 2637: #define ASC_MC_SDTR_DONE 0x00B6 ! 2638: #define ASC_MC_NUMBER_OF_QUEUED_CMD 0x00C0 ! 2639: #define ASC_MC_NUMBER_OF_MAX_CMD 0x00D0 ! 2640: #define ASC_MC_DEVICE_HSHK_CFG_TABLE 0x0100 ! 2641: #define ASC_MC_WDTR_ABLE 0x0120 /* Wide Transfer TID bitmask. */ ! 2642: #define ASC_MC_CONTROL_FLAG 0x0122 /* Microcode control flag. */ ! 2643: #define ASC_MC_WDTR_DONE 0x0124 ! 2644: #define ASC_MC_HOST_NEXT_READY 0x0128 /* Host Next Ready RQL Entry. */ ! 2645: #define ASC_MC_HOST_NEXT_DONE 0x0129 /* Host Next Done RQL Entry. */ ! 2646: ! 2647: /* ! 2648: * BIOS LRAM variable absolute offsets. ! 2649: */ ! 2650: #define BIOS_CODESEG 0x54 ! 2651: #define BIOS_CODELEN 0x56 ! 2652: #define BIOS_SIGNATURE 0x58 ! 2653: #define BIOS_VERSION 0x5A ! 2654: #define BIOS_SIGNATURE 0x58 ! 2655: ! 2656: /* ! 2657: * Microcode Control Flags ! 2658: * ! 2659: * Flags set by the Adv Library in RISC variable 'control_flag' (0x122) ! 2660: * and handled by the microcode. ! 2661: */ ! 2662: #define CONTROL_FLAG_IGNORE_PERR 0x0001 /* Ignore DMA Parity Errors */ ! 2663: ! 2664: /* ! 2665: * ASC_MC_DEVICE_HSHK_CFG_TABLE microcode table or HSHK_CFG register format ! 2666: */ ! 2667: #define HSHK_CFG_WIDE_XFR 0x8000 ! 2668: #define HSHK_CFG_RATE 0x0F00 ! 2669: #define HSHK_CFG_OFFSET 0x001F ! 2670: ! 2671: /* ! 2672: * LRAM RISC Queue Lists (LRAM addresses 0x1200 - 0x19FF) ! 2673: * ! 2674: * Each of the 255 Adv Library/Microcode RISC queue lists or mailboxes ! 2675: * starting at LRAM address 0x1200 is 8 bytes and has the following ! 2676: * structure. Only 253 of these are actually used for command queues. ! 2677: */ ! 2678: ! 2679: #define ASC_MC_RISC_Q_LIST_BASE 0x1200 ! 2680: #define ASC_MC_RISC_Q_LIST_SIZE 0x0008 ! 2681: #define ASC_MC_RISC_Q_TOTAL_CNT 0x00FF /* Num. queue slots in LRAM. */ ! 2682: #define ASC_MC_RISC_Q_FIRST 0x0001 ! 2683: #define ASC_MC_RISC_Q_LAST 0x00FF ! 2684: ! 2685: #define ASC_DEF_MAX_HOST_QNG 0xFD /* Max. number of host commands (253) */ ! 2686: #define ASC_DEF_MIN_HOST_QNG 0x10 /* Min. number of host commands (16) */ ! 2687: #define ASC_DEF_MAX_DVC_QNG 0x3F /* Max. number commands per device (63) */ ! 2688: #define ASC_DEF_MIN_DVC_QNG 0x04 /* Min. number commands per device (4) */ ! 2689: ! 2690: /* RISC Queue List structure - 8 bytes */ ! 2691: #define RQL_FWD 0 /* forward pointer (1 byte) */ ! 2692: #define RQL_BWD 1 /* backward pointer (1 byte) */ ! 2693: #define RQL_STATE 2 /* state byte - free, ready, done, aborted (1 byte) */ ! 2694: #define RQL_TID 3 /* request target id (1 byte) */ ! 2695: #define RQL_PHYADDR 4 /* request physical pointer (4 bytes) */ ! 2696: ! 2697: /* RISC Queue List state values */ ! 2698: #define ASC_MC_QS_FREE 0x00 ! 2699: #define ASC_MC_QS_READY 0x01 ! 2700: #define ASC_MC_QS_DONE 0x40 ! 2701: #define ASC_MC_QS_ABORTED 0x80 ! 2702: ! 2703: /* RISC Queue List pointer values */ ! 2704: #define ASC_MC_NULL_Q 0x00 /* NULL_Q == 0 */ ! 2705: #define ASC_MC_BIOS_Q 0xFF /* BIOS_Q = 255 */ ! 2706: ! 2707: /* ASC_SCSI_REQ_Q 'cntl' field values */ ! 2708: #define ASC_MC_QC_START_MOTOR 0x02 /* Issue start motor. */ ! 2709: #define ASC_MC_QC_NO_OVERRUN 0x04 /* Don't report overrun. */ ! 2710: #define ASC_MC_QC_FIRST_DMA 0x08 /* Internal microcode flag. */ ! 2711: #define ASC_MC_QC_ABORTED 0x10 /* Request aborted by host. */ ! 2712: #define ASC_MC_QC_REQ_SENSE 0x20 /* Auto-Request Sense. */ ! 2713: #define ASC_MC_QC_DOS_REQ 0x80 /* Request issued by DOS. */ ! 2714: ! 2715: ! 2716: /* ! 2717: * ASC_SCSI_REQ_Q 'a_flag' definitions ! 2718: * ! 2719: * The Adv Library should limit use to the lower nibble (4 bits) of ! 2720: * a_flag. Drivers are free to use the upper nibble (4 bits) of a_flag. ! 2721: */ ! 2722: #define ADV_POLL_REQUEST 0x01 /* poll for request completion */ ! 2723: #define ADV_SCSIQ_DONE 0x02 /* request done */ ! 2724: ! 2725: /* ! 2726: * Adapter temporary configuration structure ! 2727: * ! 2728: * This structure can be discarded after initialization. Don't add ! 2729: * fields here needed after initialization. ! 2730: * ! 2731: * Field naming convention: ! 2732: * ! 2733: * *_enable indicates the field enables or disables a feature. The ! 2734: * value of the field is never reset. ! 2735: */ ! 2736: typedef struct adv_dvc_cfg { ! 2737: ushort disc_enable; /* enable disconnection */ ! 2738: uchar chip_version; /* chip version */ ! 2739: uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */ ! 2740: ushort pci_device_id; /* PCI device code number */ ! 2741: ushort lib_version; /* Adv Library version number */ ! 2742: ushort control_flag; /* Microcode Control Flag */ ! 2743: ushort mcode_date; /* Microcode date */ ! 2744: ushort mcode_version; /* Microcode version */ ! 2745: ushort pci_slot_info; /* high byte device/function number */ ! 2746: /* bits 7-3 device num., bits 2-0 function num. */ ! 2747: /* low byte bus num. */ ! 2748: ushort bios_boot_wait; /* BIOS boot time delay */ ! 2749: ushort serial1; /* EEPROM serial number word 1 */ ! 2750: ushort serial2; /* EEPROM serial number word 2 */ ! 2751: ushort serial3; /* EEPROM serial number word 3 */ ! 2752: } ADV_DVC_CFG; ! 2753: ! 2754: /* ! 2755: * Adapter operation variable structure. ! 2756: * ! 2757: * One structure is required per host adapter. ! 2758: * ! 2759: * Field naming convention: ! 2760: * ! 2761: * *_able indicates both whether a feature should be enabled or disabled ! 2762: * and whether a device isi capable of the feature. At initialization ! 2763: * this field may be set, but later if a device is found to be incapable ! 2764: * of the feature, the field is cleared. ! 2765: */ ! 2766: typedef struct adv_dvc_var { ! 2767: AdvPortAddr iop_base; /* I/O port address */ ! 2768: ushort err_code; /* fatal error code */ ! 2769: ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */ ! 2770: Ptr2Func isr_callback; /* pointer to function, called in AdvISR() */ ! 2771: Ptr2Func sbreset_callback; /* pointer to function, called in AdvISR() */ ! 2772: ushort wdtr_able; /* try WDTR for a device */ ! 2773: ushort sdtr_able; /* try SDTR for a device */ ! 2774: ushort ultra_able; /* try SDTR Ultra speed for a device */ ! 2775: ushort tagqng_able; /* try tagged queuing with a device */ ! 2776: uchar max_dvc_qng; /* maximum number of tagged commands per device */ ! 2777: ushort start_motor; /* start motor command allowed */ ! 2778: uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */ ! 2779: uchar chip_no; /* should be assigned by caller */ ! 2780: uchar max_host_qng; /* maximum number of Q'ed command allowed */ ! 2781: uchar cur_host_qng; /* total number of queue command */ ! 2782: uchar irq_no; /* IRQ number */ ! 2783: ushort no_scam; /* scam_tolerant of EEPROM */ ! 2784: ushort idle_cmd_done; /* microcode idle command done set by AdvISR() */ ! 2785: ulong drv_ptr; /* driver pointer to private structure */ ! 2786: uchar chip_scsi_id; /* chip SCSI target ID */ ! 2787: /* ! 2788: * Note: The following fields will not be used after initialization. The ! 2789: * driver may discard the buffer after initialization is done. ! 2790: */ ! 2791: ADV_DVC_CFG *cfg; /* temporary configuration structure */ ! 2792: } ADV_DVC_VAR; ! 2793: ! 2794: #define NO_OF_SG_PER_BLOCK 15 ! 2795: ! 2796: typedef struct asc_sg_block { ! 2797: uchar reserved1; ! 2798: uchar reserved2; ! 2799: uchar first_entry_no; /* starting entry number */ ! 2800: uchar last_entry_no; /* last entry number */ ! 2801: struct asc_sg_block *sg_ptr; /* links to the next sg block */ ! 2802: struct { ! 2803: ulong sg_addr; /* SG element address */ ! 2804: ulong sg_count; /* SG element count */ ! 2805: } sg_list[NO_OF_SG_PER_BLOCK]; ! 2806: } ADV_SG_BLOCK; ! 2807: ! 2808: /* ! 2809: * ASC_SCSI_REQ_Q - microcode request structure ! 2810: * ! 2811: * All fields in this structure up to byte 60 are used by the microcode. ! 2812: * The microcode makes assumptions about the size and ordering of fields ! 2813: * in this structure. Do not change the structure definition here without ! 2814: * coordinating the change with the microcode. ! 2815: */ ! 2816: typedef struct adv_scsi_req_q { ! 2817: uchar cntl; /* Ucode flags and state (ASC_MC_QC_*). */ ! 2818: uchar sg_entry_cnt; /* SG element count. Zero for no SG. */ ! 2819: uchar target_id; /* Device target identifier. */ ! 2820: uchar target_lun; /* Device target logical unit number. */ ! 2821: ulong data_addr; /* Data buffer physical address. */ ! 2822: ulong data_cnt; /* Data count. Ucode sets to residual. */ ! 2823: ulong sense_addr; /* Sense buffer physical address. */ ! 2824: ulong srb_ptr; /* Driver request pointer. */ ! 2825: uchar a_flag; /* Adv Library flag field. */ ! 2826: uchar sense_len; /* Auto-sense length. Ucode sets to residual. */ ! 2827: uchar cdb_len; /* SCSI CDB length. */ ! 2828: uchar tag_code; /* SCSI-2 Tag Queue Code: 00, 20-22. */ ! 2829: uchar done_status; /* Completion status. */ ! 2830: uchar scsi_status; /* SCSI status byte. */ ! 2831: uchar host_status; /* Ucode host status. */ ! 2832: uchar ux_sg_ix; /* Ucode working SG variable. */ ! 2833: uchar cdb[12]; /* SCSI command block. */ ! 2834: ulong sg_real_addr; /* SG list physical address. */ ! 2835: struct adv_scsi_req_q *free_scsiq_link; ! 2836: ulong ux_wk_data_cnt; /* Saved data count at disconnection. */ ! 2837: struct adv_scsi_req_q *scsiq_ptr; ! 2838: ADV_SG_BLOCK *sg_list_ptr; /* SG list virtual address. */ ! 2839: /* ! 2840: * End of microcode structure - 60 bytes. The rest of the structure ! 2841: * is used by the Adv Library and ignored by the microcode. ! 2842: */ ! 2843: ulong vsense_addr; /* Sense buffer virtual address. */ ! 2844: ulong vdata_addr; /* Data buffer virtual address. */ ! 2845: uchar orig_sense_len; /* Original length of sense buffer. */ ! 2846: } ADV_SCSI_REQ_Q; /* BIOS - 70 bytes, DOS - 76 bytes, W95, WNT - 69 bytes */ ! 2847: ! 2848: /* ! 2849: * Microcode idle loop commands ! 2850: */ ! 2851: #define IDLE_CMD_COMPLETED 0 ! 2852: #define IDLE_CMD_STOP_CHIP 0x0001 ! 2853: #define IDLE_CMD_STOP_CHIP_SEND_INT 0x0002 ! 2854: #define IDLE_CMD_SEND_INT 0x0004 ! 2855: #define IDLE_CMD_ABORT 0x0008 ! 2856: #define IDLE_CMD_DEVICE_RESET 0x0010 ! 2857: #define IDLE_CMD_SCSI_RESET 0x0020 ! 2858: ! 2859: /* ! 2860: * AdvSendIdleCmd() flag definitions. ! 2861: */ ! 2862: #define ADV_NOWAIT 0x01 ! 2863: ! 2864: /* ! 2865: * Wait loop time out values. ! 2866: */ ! 2867: #define SCSI_WAIT_10_SEC 10 /* 10 seconds */ ! 2868: #define SCSI_MS_PER_SEC 1000 /* milliseconds per second */ ! 2869: ! 2870: /* ! 2871: * Device drivers must define the following functions. ! 2872: */ ! 2873: STATIC int DvcEnterCritical(void); ! 2874: STATIC void DvcLeaveCritical(int); ! 2875: STATIC void DvcSleepMilliSecond(ulong); ! 2876: STATIC uchar DvcAdvReadPCIConfigByte(ADV_DVC_VAR *, ushort); ! 2877: STATIC void DvcAdvWritePCIConfigByte(ADV_DVC_VAR *, ushort, uchar); ! 2878: STATIC ulong DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *, ! 2879: uchar *, long *, int); ! 2880: STATIC void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort); ! 2881: ! 2882: /* ! 2883: * Adv Library functions available to drivers. ! 2884: */ ! 2885: STATIC int AdvExeScsiQueue(ADV_DVC_VAR *, ! 2886: ADV_SCSI_REQ_Q *); ! 2887: STATIC int AdvISR(ADV_DVC_VAR *); ! 2888: STATIC int AdvInitGetConfig(ADV_DVC_VAR *); ! 2889: STATIC int AdvInitAsc3550Driver(ADV_DVC_VAR *); ! 2890: STATIC int AdvResetSB(ADV_DVC_VAR *); ! 2891: ! 2892: /* ! 2893: * Internal Adv Library functions. ! 2894: */ ! 2895: STATIC int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ulong, int); ! 2896: STATIC void AdvResetChip(ADV_DVC_VAR *); ! 2897: STATIC int AdvSendScsiCmd(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); ! 2898: STATIC void AdvInquiryHandling(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); ! 2899: STATIC int AdvInitFromEEP(ADV_DVC_VAR *); ! 2900: STATIC ushort AdvGetEEPConfig(AdvPortAddr, ADVEEP_CONFIG *); ! 2901: STATIC void AdvSetEEPConfig(AdvPortAddr, ADVEEP_CONFIG *); ! 2902: STATIC void AdvWaitEEPCmd(AdvPortAddr); ! 2903: STATIC ushort AdvReadEEPWord(AdvPortAddr, int); ! 2904: STATIC void AdvResetSCSIBus(ADV_DVC_VAR *); ! 2905: ! 2906: /* ! 2907: * PCI Bus Definitions ! 2908: */ ! 2909: #define AscPCICmdRegBits_BusMastering 0x0007 ! 2910: #define AscPCICmdRegBits_ParErrRespCtrl 0x0040 ! 2911: ! 2912: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0) ! 2913: ! 2914: /* Read byte from a register. */ ! 2915: #define AdvReadByteRegister(iop_base, reg_off) \ ! 2916: (inp((iop_base) + (reg_off))) ! 2917: ! 2918: /* Write byte to a register. */ ! 2919: #define AdvWriteByteRegister(iop_base, reg_off, byte) \ ! 2920: (outp((iop_base) + (reg_off), (byte))) ! 2921: ! 2922: /* Read word (2 bytes) from a register. */ ! 2923: #define AdvReadWordRegister(iop_base, reg_off) \ ! 2924: (inpw((iop_base) + (reg_off))) ! 2925: ! 2926: /* Write word (2 bytes) to a register. */ ! 2927: #define AdvWriteWordRegister(iop_base, reg_off, word) \ ! 2928: (outpw((iop_base) + (reg_off), (word))) ! 2929: ! 2930: /* Read byte from LRAM. */ ! 2931: #define AdvReadByteLram(iop_base, addr, byte) \ ! 2932: do { \ ! 2933: outpw((iop_base) + IOPW_RAM_ADDR, (addr)); \ ! 2934: (byte) = inp((iop_base) + IOPB_RAM_DATA); \ ! 2935: } while (0) ! 2936: ! 2937: /* Write byte to LRAM. */ ! 2938: #define AdvWriteByteLram(iop_base, addr, byte) \ ! 2939: (outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \ ! 2940: outp((iop_base) + IOPB_RAM_DATA, (byte))) ! 2941: ! 2942: /* Read word (2 bytes) from LRAM. */ ! 2943: #define AdvReadWordLram(iop_base, addr, word) \ ! 2944: do { \ ! 2945: outpw((iop_base) + IOPW_RAM_ADDR, (addr)); \ ! 2946: (word) = inpw((iop_base) + IOPW_RAM_DATA); \ ! 2947: } while (0) ! 2948: ! 2949: /* Write word (2 bytes) to LRAM. */ ! 2950: #define AdvWriteWordLram(iop_base, addr, word) \ ! 2951: (outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \ ! 2952: outpw((iop_base) + IOPW_RAM_DATA, (word))) ! 2953: ! 2954: /* Write double word (4 bytes) to LRAM */ ! 2955: /* Because of unspecified C language ordering don't use auto-increment. */ ! 2956: #define AdvWriteDWordLram(iop_base, addr, dword) \ ! 2957: ((outpw((iop_base) + IOPW_RAM_ADDR, (addr)), \ ! 2958: outpw((iop_base) + IOPW_RAM_DATA, (ushort) ((dword) & 0xFFFF))), \ ! 2959: (outpw((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \ ! 2960: outpw((iop_base) + IOPW_RAM_DATA, (ushort) ((dword >> 16) & 0xFFFF)))) ! 2961: ! 2962: /* Read word (2 bytes) from LRAM assuming that the address is already set. */ ! 2963: #define AdvReadWordAutoIncLram(iop_base) \ ! 2964: (inpw((iop_base) + IOPW_RAM_DATA)) ! 2965: ! 2966: /* Write word (2 bytes) to LRAM assuming that the address is already set. */ ! 2967: #define AdvWriteWordAutoIncLram(iop_base, word) \ ! 2968: (outpw((iop_base) + IOPW_RAM_DATA, (word))) ! 2969: ! 2970: #else /* version >= v1,3,0 */ ! 2971: ! 2972: /* Read byte from a register. */ ! 2973: #define AdvReadByteRegister(iop_base, reg_off) \ ! 2974: (ADV_MEM_READB((iop_base) + (reg_off))) ! 2975: ! 2976: /* Write byte to a register. */ ! 2977: #define AdvWriteByteRegister(iop_base, reg_off, byte) \ ! 2978: (ADV_MEM_WRITEB((iop_base) + (reg_off), (byte))) ! 2979: ! 2980: /* Read word (2 bytes) from a register. */ ! 2981: #define AdvReadWordRegister(iop_base, reg_off) \ ! 2982: (ADV_MEM_READW((iop_base) + (reg_off))) ! 2983: ! 2984: /* Write word (2 bytes) to a register. */ ! 2985: #define AdvWriteWordRegister(iop_base, reg_off, word) \ ! 2986: (ADV_MEM_WRITEW((iop_base) + (reg_off), (word))) ! 2987: ! 2988: /* Read byte from LRAM. */ ! 2989: #define AdvReadByteLram(iop_base, addr, byte) \ ! 2990: do { \ ! 2991: ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \ ! 2992: (byte) = ADV_MEM_READB((iop_base) + IOPB_RAM_DATA); \ ! 2993: } while (0) ! 2994: ! 2995: /* Write byte to LRAM. */ ! 2996: #define AdvWriteByteLram(iop_base, addr, byte) \ ! 2997: (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \ ! 2998: ADV_MEM_WRITEB((iop_base) + IOPB_RAM_DATA, (byte))) ! 2999: ! 3000: /* Read word (2 bytes) from LRAM. */ ! 3001: #define AdvReadWordLram(iop_base, addr, word) \ ! 3002: do { \ ! 3003: ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)); \ ! 3004: (word) = ADV_MEM_READW((iop_base) + IOPW_RAM_DATA); \ ! 3005: } while (0) ! 3006: ! 3007: /* Write word (2 bytes) to LRAM. */ ! 3008: #define AdvWriteWordLram(iop_base, addr, word) \ ! 3009: (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \ ! 3010: ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word))) ! 3011: ! 3012: /* Write double word (4 bytes) to LRAM */ ! 3013: /* Because of unspecified C language ordering don't use auto-increment. */ ! 3014: #define AdvWriteDWordLram(iop_base, addr, dword) \ ! 3015: ((ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr)), \ ! 3016: ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \ ! 3017: (ushort) ((dword) & 0xFFFF))), \ ! 3018: (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_ADDR, (addr) + 2), \ ! 3019: ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, \ ! 3020: (ushort) ((dword >> 16) & 0xFFFF)))) ! 3021: ! 3022: /* Read word (2 bytes) from LRAM assuming that the address is already set. */ ! 3023: #define AdvReadWordAutoIncLram(iop_base) \ ! 3024: (ADV_MEM_READW((iop_base) + IOPW_RAM_DATA)) ! 3025: ! 3026: /* Write word (2 bytes) to LRAM assuming that the address is already set. */ ! 3027: #define AdvWriteWordAutoIncLram(iop_base, word) \ ! 3028: (ADV_MEM_WRITEW((iop_base) + IOPW_RAM_DATA, (word))) ! 3029: ! 3030: #endif /* version >= v1,3,0 */ ! 3031: ! 3032: /* ! 3033: * Define macro to check for Condor signature. ! 3034: * ! 3035: * Evaluate to ADV_TRUE if a Condor chip is found the specified port ! 3036: * address 'iop_base'. Otherwise evalue to ADV_FALSE. ! 3037: */ ! 3038: #define AdvFindSignature(iop_base) \ ! 3039: (((AdvReadByteRegister((iop_base), IOPB_CHIP_ID_1) == \ ! 3040: ADV_CHIP_ID_BYTE) && \ ! 3041: (AdvReadWordRegister((iop_base), IOPW_CHIP_ID_0) == \ ! 3042: ADV_CHIP_ID_WORD)) ? ADV_TRUE : ADV_FALSE) ! 3043: ! 3044: /* ! 3045: * Define macro to Return the version number of the chip at 'iop_base'. ! 3046: * ! 3047: * The second parameter 'bus_type' is currently unused. ! 3048: */ ! 3049: #define AdvGetChipVersion(iop_base, bus_type) \ ! 3050: AdvReadByteRegister((iop_base), IOPB_CHIP_TYPE_REV) ! 3051: ! 3052: /* ! 3053: * Abort an SRB in the chip's RISC Memory. The 'srb_ptr' argument must ! 3054: * match the ASC_SCSI_REQ_Q 'srb_ptr' field. ! 3055: * ! 3056: * If the request has not yet been sent to the device it will simply be ! 3057: * aborted from RISC memory. If the request is disconnected it will be ! 3058: * aborted on reselection by sending an Abort Message to the target ID. ! 3059: * ! 3060: * Return value: ! 3061: * ADV_TRUE(1) - Queue was successfully aborted. ! 3062: * ADV_FALSE(0) - Queue was not found on the active queue list. ! 3063: */ ! 3064: #define AdvAbortSRB(asc_dvc, srb_ptr) \ ! 3065: AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_ABORT, \ ! 3066: (ulong) (srb_ptr), 0) ! 3067: ! 3068: /* ! 3069: * Send a Bus Device Reset Message to the specified target ID. ! 3070: * ! 3071: * All outstanding commands will be purged if sending the ! 3072: * Bus Device Reset Message is successful. ! 3073: * ! 3074: * Return Value: ! 3075: * ADV_TRUE(1) - All requests on the target are purged. ! 3076: * ADV_FALSE(0) - Couldn't issue Bus Device Reset Message; Requests ! 3077: * are not purged. ! 3078: */ ! 3079: #define AdvResetDevice(asc_dvc, target_id) \ ! 3080: AdvSendIdleCmd((asc_dvc), (ushort) IDLE_CMD_DEVICE_RESET, \ ! 3081: (ulong) (target_id), 0) ! 3082: ! 3083: /* ! 3084: * SCSI Wide Type definition. ! 3085: */ ! 3086: #define ADV_SCSI_BIT_ID_TYPE ushort ! 3087: ! 3088: /* ! 3089: * AdvInitScsiTarget() 'cntl_flag' options. ! 3090: */ ! 3091: #define ADV_SCAN_LUN 0x01 ! 3092: #define ADV_CAPINFO_NOLUN 0x02 ! 3093: ! 3094: /* ! 3095: * Convert target id to target id bit mask. ! 3096: */ ! 3097: #define ADV_TID_TO_TIDMASK(tid) (0x01 << ((tid) & ADV_MAX_TID)) ! 3098: ! 3099: /* ! 3100: * ASC_SCSI_REQ_Q 'done_status' and 'host_status' return values. ! 3101: */ ! 3102: ! 3103: #define QD_NO_STATUS 0x00 /* Request not completed yet. */ ! 3104: #define QD_NO_ERROR 0x01 ! 3105: #define QD_ABORTED_BY_HOST 0x02 ! 3106: #define QD_WITH_ERROR 0x04 ! 3107: ! 3108: #define QHSTA_NO_ERROR 0x00 ! 3109: #define QHSTA_M_SEL_TIMEOUT 0x11 ! 3110: #define QHSTA_M_DATA_OVER_RUN 0x12 ! 3111: #define QHSTA_M_UNEXPECTED_BUS_FREE 0x13 ! 3112: #define QHSTA_M_QUEUE_ABORTED 0x15 ! 3113: #define QHSTA_M_SXFR_SDMA_ERR 0x16 /* SXFR_STATUS SCSI DMA Error */ ! 3114: #define QHSTA_M_SXFR_SXFR_PERR 0x17 /* SXFR_STATUS SCSI Bus Parity Error */ ! 3115: #define QHSTA_M_RDMA_PERR 0x18 /* RISC PCI DMA parity error */ ! 3116: #define QHSTA_M_SXFR_OFF_UFLW 0x19 /* SXFR_STATUS Offset Underflow */ ! 3117: #define QHSTA_M_SXFR_OFF_OFLW 0x20 /* SXFR_STATUS Offset Overflow */ ! 3118: #define QHSTA_M_SXFR_WD_TMO 0x21 /* SXFR_STATUS Watchdog Timeout */ ! 3119: #define QHSTA_M_SXFR_DESELECTED 0x22 /* SXFR_STATUS Deselected */ ! 3120: /* Note: QHSTA_M_SXFR_XFR_OFLW is identical to QHSTA_M_DATA_OVER_RUN. */ ! 3121: #define QHSTA_M_SXFR_XFR_OFLW 0x12 /* SXFR_STATUS Transfer Overflow */ ! 3122: #define QHSTA_M_SXFR_XFR_PH_ERR 0x24 /* SXFR_STATUS Transfer Phase Error */ ! 3123: #define QHSTA_M_SXFR_UNKNOWN_ERROR 0x25 /* SXFR_STATUS Unknown Error */ ! 3124: #define QHSTA_M_WTM_TIMEOUT 0x41 ! 3125: #define QHSTA_M_BAD_CMPL_STATUS_IN 0x42 ! 3126: #define QHSTA_M_NO_AUTO_REQ_SENSE 0x43 ! 3127: #define QHSTA_M_AUTO_REQ_SENSE_FAIL 0x44 ! 3128: #define QHSTA_M_INVALID_DEVICE 0x45 /* Bad target ID */ ! 3129: ! 3130: typedef int (* ADV_ISR_CALLBACK) ! 3131: (ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); ! 3132: ! 3133: typedef int (* ADV_SBRESET_CALLBACK) ! 3134: (ADV_DVC_VAR *); ! 3135: ! 3136: /* ! 3137: * Default EEPROM Configuration structure defined in a_init.c. ! 3138: */ ! 3139: extern ADVEEP_CONFIG Default_EEPROM_Config; ! 3140: ! 3141: /* ! 3142: * DvcGetPhyAddr() flag arguments ! 3143: */ ! 3144: #define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */ ! 3145: #define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */ ! 3146: #define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */ ! 3147: #define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */ ! 3148: #define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */ ! 3149: ! 3150: /* Return the address that is aligned at the next doubleword >= to 'addr'. */ ! 3151: #define ADV_DWALIGN(addr) (((ulong) (addr) + 0x3) & ~0x3) ! 3152: ! 3153: /* ! 3154: * Total contiguous memory needed for driver SG blocks. ! 3155: * ! 3156: * ADV_MAX_SG_LIST must be defined by a driver. It is the maximum ! 3157: * number of scatter-gather elements the driver supports in a ! 3158: * single request. ! 3159: */ ! 3160: ! 3161: #ifndef ADV_MAX_SG_LIST ! 3162: Forced Error: Driver must define ADV_MAX_SG_LIST. ! 3163: #endif /* ADV_MAX_SG_LIST */ ! 3164: ! 3165: #define ADV_SG_LIST_MAX_BYTE_SIZE \ ! 3166: (sizeof(ADV_SG_BLOCK) * \ ! 3167: ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)) ! 3168: ! 3169: /* ! 3170: * A driver may optionally define the assertion macro ADV_ASSERT() in ! 3171: * its d_os_dep.h file. If the macro has not already been defined, ! 3172: * then define the macro to a no-op. ! 3173: */ ! 3174: #ifndef ADV_ASSERT ! 3175: #define ADV_ASSERT(a) ! 3176: #endif /* ADV_ASSERT */ ! 3177: ! 3178: ! 3179: /* ! 3180: * --- Driver Constants and Macros ! 3181: */ ! 3182: ! 3183: #define ASC_NUM_BOARD_SUPPORTED 16 ! 3184: #define ASC_NUM_IOPORT_PROBE 4 ! 3185: #define ASC_NUM_BUS 4 ! 3186: ! 3187: /* Reference Scsi_Host hostdata */ ! 3188: #define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata)) ! 3189: ! 3190: /* asc_board_t flags */ ! 3191: #define ASC_HOST_IN_RESET 0x01 ! 3192: #define ASC_HOST_IN_ABORT 0x02 ! 3193: #define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */ ! 3194: #define ASC_SELECT_QUEUE_DEPTHS 0x08 ! 3195: ! 3196: #define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0) ! 3197: #define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD) ! 3198: ! 3199: #define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */ ! 3200: ! 3201: /* ! 3202: * If the Linux kernel version supports freeing initialization code ! 3203: * and data after loading, define macros for this purpose. These macros ! 3204: * are not used when the driver is built as a module, cf. linux/init.h. ! 3205: */ ! 3206: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,23) ! 3207: #define ASC_INITFUNC(func) func ! 3208: #define ASC_INITDATA ! 3209: #define ASC_INIT ! 3210: #else /* version >= v2.1.23 */ ! 3211: #define ASC_INITFUNC(func) __initfunc(func) ! 3212: #define ASC_INITDATA __initdata ! 3213: #define ASC_INIT __init ! 3214: #endif /* version >= v2.1.23 */ ! 3215: ! 3216: #define ASC_INFO_SIZE 128 /* advansys_info() line size */ ! 3217: ! 3218: /* /proc/scsi/advansys/[0...] related definitions */ ! 3219: #define ASC_PRTBUF_SIZE 2048 ! 3220: #define ASC_PRTLINE_SIZE 160 ! 3221: ! 3222: #define ASC_PRT_NEXT() \ ! 3223: if (cp) { \ ! 3224: totlen += len; \ ! 3225: leftlen -= len; \ ! 3226: if (leftlen == 0) { \ ! 3227: return totlen; \ ! 3228: } \ ! 3229: cp += len; \ ! 3230: } ! 3231: ! 3232: #define ASC_MIN(a, b) (((a) < (b)) ? (a) : (b)) ! 3233: ! 3234: /* Asc Library return codes */ ! 3235: #define ASC_TRUE 1 ! 3236: #define ASC_FALSE 0 ! 3237: #define ASC_NOERROR 1 ! 3238: #define ASC_BUSY 0 ! 3239: #define ASC_ERROR (-1) ! 3240: ! 3241: /* Scsi_Cmnd function return codes */ ! 3242: #define STATUS_BYTE(byte) (byte) ! 3243: #define MSG_BYTE(byte) ((byte) << 8) ! 3244: #define HOST_BYTE(byte) ((byte) << 16) ! 3245: #define DRIVER_BYTE(byte) ((byte) << 24) ! 3246: ! 3247: /* ! 3248: * The following definitions and macros are OS independent interfaces to ! 3249: * the queue functions: ! 3250: * REQ - SCSI request structure ! 3251: * REQP - pointer to SCSI request structure ! 3252: * REQPTID(reqp) - reqp's target id ! 3253: * REQPNEXT(reqp) - reqp's next pointer ! 3254: * REQPNEXTP(reqp) - pointer to reqp's next pointer ! 3255: * REQPTIME(reqp) - reqp's time stamp value ! 3256: * REQTIMESTAMP() - system time stamp value ! 3257: */ ! 3258: typedef Scsi_Cmnd REQ, *REQP; ! 3259: #define REQPNEXT(reqp) ((REQP) ((reqp)->host_scribble)) ! 3260: #define REQPNEXTP(reqp) ((REQP *) &((reqp)->host_scribble)) ! 3261: #define REQPTID(reqp) ((reqp)->target) ! 3262: #define REQPTIME(reqp) ((reqp)->SCp.this_residual) ! 3263: #define REQTIMESTAMP() (jiffies) ! 3264: ! 3265: #define REQTIMESTAT(function, ascq, reqp, tid) \ ! 3266: { \ ! 3267: /* ! 3268: * If the request time stamp is less than the system time stamp, then \ ! 3269: * maybe the system time stamp wrapped. Set the request time to zero.\ ! 3270: */ \ ! 3271: if (REQPTIME(reqp) <= REQTIMESTAMP()) { \ ! 3272: REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \ ! 3273: } else { \ ! 3274: /* Indicate an error occurred with the assertion. */ \ ! 3275: ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \ ! 3276: REQPTIME(reqp) = 0; \ ! 3277: } \ ! 3278: /* Handle first minimum time case without external initialization. */ \ ! 3279: if (((ascq)->q_tot_cnt[tid] == 1) || \ ! 3280: (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \ ! 3281: (ascq)->q_min_tim[tid] = REQPTIME(reqp); \ ! 3282: ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \ ! 3283: (function), (tid), (ascq)->q_min_tim[tid]); \ ! 3284: } \ ! 3285: if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \ ! 3286: (ascq)->q_max_tim[tid] = REQPTIME(reqp); \ ! 3287: ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \ ! 3288: (function), tid, (ascq)->q_max_tim[tid]); \ ! 3289: } \ ! 3290: (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \ ! 3291: /* Reset the time stamp field. */ \ ! 3292: REQPTIME(reqp) = 0; \ ! 3293: } ! 3294: ! 3295: /* asc_enqueue() flags */ ! 3296: #define ASC_FRONT 1 ! 3297: #define ASC_BACK 2 ! 3298: ! 3299: /* asc_dequeue_list() argument */ ! 3300: #define ASC_TID_ALL (-1) ! 3301: ! 3302: /* Return non-zero, if the queue is empty. */ ! 3303: #define ASC_QUEUE_EMPTY(ascq) ((ascq)->q_tidmask == 0) ! 3304: ! 3305: /* PCI configuration declarations */ ! 3306: ! 3307: #define PCI_BASE_CLASS_PREDEFINED 0x00 ! 3308: #define PCI_BASE_CLASS_MASS_STORAGE 0x01 ! 3309: #define PCI_BASE_CLASS_NETWORK 0x02 ! 3310: #define PCI_BASE_CLASS_DISPLAY 0x03 ! 3311: #define PCI_BASE_CLASS_MULTIMEDIA 0x04 ! 3312: #define PCI_BASE_CLASS_MEMORY_CONTROLLER 0x05 ! 3313: #define PCI_BASE_CLASS_BRIDGE_DEVICE 0x06 ! 3314: ! 3315: /* MASS STORAGE */ ! 3316: #define PCI_SUB_CLASS_SCSI_CONTROLLER 0x00 ! 3317: #define PCI_SUB_CLASS_IDE_CONTROLLER 0x01 ! 3318: #define PCI_SUB_CLASS_FLOPPY_DISK_CONTROLLER 0x02 ! 3319: #define PCI_SUB_CLASS_IPI_BUS_CONTROLLER 0x03 ! 3320: #define PCI_SUB_CLASS_OTHER_MASS_CONTROLLER 0x80 ! 3321: ! 3322: /* NETWORK CONTROLLER */ ! 3323: #define PCI_SUB_CLASS_ETHERNET_CONTROLLER 0x00 ! 3324: #define PCI_SUB_CLASS_TOKEN_RING_CONTROLLER 0x01 ! 3325: #define PCI_SUB_CLASS_FDDI_CONTROLLER 0x02 ! 3326: #define PCI_SUB_CLASS_OTHER_NETWORK_CONTROLLER 0x80 ! 3327: ! 3328: /* DISPLAY CONTROLLER */ ! 3329: #define PCI_SUB_CLASS_VGA_CONTROLLER 0x00 ! 3330: #define PCI_SUB_CLASS_XGA_CONTROLLER 0x01 ! 3331: #define PCI_SUB_CLASS_OTHER_DISPLAY_CONTROLLER 0x80 ! 3332: ! 3333: /* MULTIMEDIA CONTROLLER */ ! 3334: #define PCI_SUB_CLASS_VIDEO_DEVICE 0x00 ! 3335: #define PCI_SUB_CLASS_AUDIO_DEVICE 0x01 ! 3336: #define PCI_SUB_CLASS_OTHER_MULTIMEDIA_DEVICE 0x80 ! 3337: ! 3338: /* MEMORY CONTROLLER */ ! 3339: #define PCI_SUB_CLASS_RAM_CONTROLLER 0x00 ! 3340: #define PCI_SUB_CLASS_FLASH_CONTROLLER 0x01 ! 3341: #define PCI_SUB_CLASS_OTHER_MEMORY_CONTROLLER 0x80 ! 3342: ! 3343: /* BRIDGE CONTROLLER */ ! 3344: #define PCI_SUB_CLASS_HOST_BRIDGE_CONTROLLER 0x00 ! 3345: #define PCI_SUB_CLASS_ISA_BRIDGE_CONTROLLER 0x01 ! 3346: #define PCI_SUB_CLASS_EISA_BRIDGE_CONTROLLER 0x02 ! 3347: #define PCI_SUB_CLASS_MC_BRIDGE_CONTROLLER 0x03 ! 3348: #define PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER 0x04 ! 3349: #define PCI_SUB_CLASS_PCMCIA_BRIDGE_CONTROLLER 0x05 ! 3350: #define PCI_SUB_CLASS_OTHER_BRIDGE_CONTROLLER 0x80 ! 3351: ! 3352: #define PCI_MAX_SLOT 0x1F ! 3353: #define PCI_MAX_BUS 0xFF ! 3354: #define PCI_IOADDRESS_MASK 0xFFFE ! 3355: #define ASC_PCI_VENDORID 0x10CD ! 3356: #define ASC_PCI_DEVICE_ID_CNT 4 /* PCI Device ID count. */ ! 3357: #define ASC_PCI_DEVICE_ID_1100 0x1100 ! 3358: #define ASC_PCI_DEVICE_ID_1200 0x1200 ! 3359: #define ASC_PCI_DEVICE_ID_1300 0x1300 ! 3360: #define ASC_PCI_DEVICE_ID_2300 0x2300 ! 3361: ! 3362: /* PCI IO Port Addresses to generate special cycle */ ! 3363: ! 3364: #define PCI_CONFIG_ADDRESS_MECH1 0x0CF8 ! 3365: #define PCI_CONFIG_DATA_MECH1 0x0CFC ! 3366: ! 3367: #define PCI_CONFIG_FORWARD_REGISTER 0x0CFA /* 0=type 0; 1=type 1; */ ! 3368: ! 3369: #define PCI_CONFIG_BUS_NUMBER_MASK 0x00FF0000 ! 3370: #define PCI_CONFIG_DEVICE_FUNCTION_MASK 0x0000FF00 ! 3371: #define PCI_CONFIG_REGISTER_NUMBER_MASK 0x000000F8 ! 3372: ! 3373: #define PCI_DEVICE_FOUND 0x0000 ! 3374: #define PCI_DEVICE_NOT_FOUND 0xffff ! 3375: ! 3376: #define SUBCLASS_OFFSET 0x0A ! 3377: #define CLASSCODE_OFFSET 0x0B ! 3378: #define VENDORID_OFFSET 0x00 ! 3379: #define DEVICEID_OFFSET 0x02 ! 3380: ! 3381: #ifndef ADVANSYS_STATS ! 3382: #define ASC_STATS(shp, counter) ! 3383: #define ASC_STATS_ADD(shp, counter, count) ! 3384: #else /* ADVANSYS_STATS */ ! 3385: #define ASC_STATS(shp, counter) \ ! 3386: (ASC_BOARDP(shp)->asc_stats.counter++) ! 3387: ! 3388: #define ASC_STATS_ADD(shp, counter, count) \ ! 3389: (ASC_BOARDP(shp)->asc_stats.counter += (count)) ! 3390: #endif /* ADVANSYS_STATS */ ! 3391: ! 3392: #define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit)) ! 3393: ! 3394: /* If the result wraps when calculating tenths, return 0. */ ! 3395: #define ASC_TENTHS(num, den) \ ! 3396: (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \ ! 3397: 0 : ((((num) * 10)/(den)) - (10 * ((num)/(den))))) ! 3398: ! 3399: /* ! 3400: * Display a message to the console. ! 3401: */ ! 3402: #define ASC_PRINT(s) \ ! 3403: { \ ! 3404: printk("advansys: "); \ ! 3405: printk(s); \ ! 3406: } ! 3407: ! 3408: #define ASC_PRINT1(s, a1) \ ! 3409: { \ ! 3410: printk("advansys: "); \ ! 3411: printk((s), (a1)); \ ! 3412: } ! 3413: ! 3414: #define ASC_PRINT2(s, a1, a2) \ ! 3415: { \ ! 3416: printk("advansys: "); \ ! 3417: printk((s), (a1), (a2)); \ ! 3418: } ! 3419: ! 3420: #define ASC_PRINT3(s, a1, a2, a3) \ ! 3421: { \ ! 3422: printk("advansys: "); \ ! 3423: printk((s), (a1), (a2), (a3)); \ ! 3424: } ! 3425: ! 3426: #define ASC_PRINT4(s, a1, a2, a3, a4) \ ! 3427: { \ ! 3428: printk("advansys: "); \ ! 3429: printk((s), (a1), (a2), (a3), (a4)); \ ! 3430: } ! 3431: ! 3432: ! 3433: #ifndef ADVANSYS_DEBUG ! 3434: ! 3435: #define ASC_DBG(lvl, s) ! 3436: #define ASC_DBG1(lvl, s, a1) ! 3437: #define ASC_DBG2(lvl, s, a1, a2) ! 3438: #define ASC_DBG3(lvl, s, a1, a2, a3) ! 3439: #define ASC_DBG4(lvl, s, a1, a2, a3, a4) ! 3440: #define ASC_DBG_PRT_SCSI_HOST(lvl, s) ! 3441: #define ASC_DBG_PRT_SCSI_CMND(lvl, s) ! 3442: #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) ! 3443: #define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) ! 3444: #define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) ! 3445: #define ADV_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) ! 3446: #define ASC_DBG_PRT_HEX(lvl, name, start, length) ! 3447: #define ASC_DBG_PRT_CDB(lvl, cdb, len) ! 3448: #define ASC_DBG_PRT_SENSE(lvl, sense, len) ! 3449: #define ASC_DBG_PRT_INQUIRY(lvl, inq, len) ! 3450: ! 3451: #else /* ADVANSYS_DEBUG */ ! 3452: ! 3453: /* ! 3454: * Debugging Message Levels: ! 3455: * 0: Errors Only ! 3456: * 1: High-Level Tracing ! 3457: * 2-N: Verbose Tracing ! 3458: */ ! 3459: ! 3460: #define ASC_DBG(lvl, s) \ ! 3461: { \ ! 3462: if (asc_dbglvl >= (lvl)) { \ ! 3463: printk(s); \ ! 3464: } \ ! 3465: } ! 3466: ! 3467: #define ASC_DBG1(lvl, s, a1) \ ! 3468: { \ ! 3469: if (asc_dbglvl >= (lvl)) { \ ! 3470: printk((s), (a1)); \ ! 3471: } \ ! 3472: } ! 3473: ! 3474: #define ASC_DBG2(lvl, s, a1, a2) \ ! 3475: { \ ! 3476: if (asc_dbglvl >= (lvl)) { \ ! 3477: printk((s), (a1), (a2)); \ ! 3478: } \ ! 3479: } ! 3480: ! 3481: #define ASC_DBG3(lvl, s, a1, a2, a3) \ ! 3482: { \ ! 3483: if (asc_dbglvl >= (lvl)) { \ ! 3484: printk((s), (a1), (a2), (a3)); \ ! 3485: } \ ! 3486: } ! 3487: ! 3488: #define ASC_DBG4(lvl, s, a1, a2, a3, a4) \ ! 3489: { \ ! 3490: if (asc_dbglvl >= (lvl)) { \ ! 3491: printk((s), (a1), (a2), (a3), (a4)); \ ! 3492: } \ ! 3493: } ! 3494: ! 3495: #define ASC_DBG_PRT_SCSI_HOST(lvl, s) \ ! 3496: { \ ! 3497: if (asc_dbglvl >= (lvl)) { \ ! 3498: asc_prt_scsi_host(s); \ ! 3499: } \ ! 3500: } ! 3501: ! 3502: #define ASC_DBG_PRT_SCSI_CMND(lvl, s) \ ! 3503: { \ ! 3504: if (asc_dbglvl >= (lvl)) { \ ! 3505: asc_prt_scsi_cmnd(s); \ ! 3506: } \ ! 3507: } ! 3508: ! 3509: #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \ ! 3510: { \ ! 3511: if (asc_dbglvl >= (lvl)) { \ ! 3512: asc_prt_asc_scsi_q(scsiqp); \ ! 3513: } \ ! 3514: } ! 3515: ! 3516: #define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) \ ! 3517: { \ ! 3518: if (asc_dbglvl >= (lvl)) { \ ! 3519: asc_prt_asc_qdone_info(qdone); \ ! 3520: } \ ! 3521: } ! 3522: ! 3523: #define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) \ ! 3524: { \ ! 3525: if (asc_dbglvl >= (lvl)) { \ ! 3526: asc_prt_adv_scsi_req_q(scsiqp); \ ! 3527: } \ ! 3528: } ! 3529: ! 3530: #define ASC_DBG_PRT_HEX(lvl, name, start, length) \ ! 3531: { \ ! 3532: if (asc_dbglvl >= (lvl)) { \ ! 3533: asc_prt_hex((name), (start), (length)); \ ! 3534: } \ ! 3535: } ! 3536: ! 3537: #define ASC_DBG_PRT_CDB(lvl, cdb, len) \ ! 3538: ASC_DBG_PRT_HEX((lvl), "CDB", (uchar *) (cdb), (len)); ! 3539: ! 3540: #define ASC_DBG_PRT_SENSE(lvl, sense, len) \ ! 3541: ASC_DBG_PRT_HEX((lvl), "SENSE", (uchar *) (sense), (len)); ! 3542: ! 3543: #define ASC_DBG_PRT_INQUIRY(lvl, inq, len) \ ! 3544: ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len)); ! 3545: #endif /* ADVANSYS_DEBUG */ ! 3546: ! 3547: #ifndef ADVANSYS_ASSERT ! 3548: #define ASC_ASSERT(a) ! 3549: #else /* ADVANSYS_ASSERT */ ! 3550: ! 3551: #define ASC_ASSERT(a) \ ! 3552: { \ ! 3553: if (!(a)) { \ ! 3554: printk("ASC_ASSERT() Failure: file %s, line %d\n", \ ! 3555: __FILE__, __LINE__); \ ! 3556: } \ ! 3557: } ! 3558: ! 3559: #endif /* ADVANSYS_ASSERT */ ! 3560: ! 3561: ! 3562: /* ! 3563: * --- Driver Structures ! 3564: */ ! 3565: ! 3566: #ifdef ADVANSYS_STATS ! 3567: ! 3568: /* Per board statistics structure */ ! 3569: struct asc_stats { ! 3570: /* Driver Entrypoint Statistics */ ! 3571: ulong command; /* # calls to advansys_command() */ ! 3572: ulong queuecommand; /* # calls to advansys_queuecommand() */ ! 3573: ulong abort; /* # calls to advansys_abort() */ ! 3574: ulong reset; /* # calls to advansys_reset() */ ! 3575: ulong biosparam; /* # calls to advansys_biosparam() */ ! 3576: ulong interrupt; /* # advansys_interrupt() calls */ ! 3577: ulong callback; /* # calls to asc/adv_isr_callback() */ ! 3578: ulong done; /* # calls to request's scsi_done function */ ! 3579: ulong build_error; /* # asc/adv_build_req() ASC_ERROR returns. */ ! 3580: ulong adv_build_noreq; /* # adv_build_req() adv_req_t alloc. fail. */ ! 3581: ulong adv_build_nosg; /* # adv_build_req() adv_sgblk_t alloc. fail. */ ! 3582: /* AscExeScsiQueue()/AdvExeScsiQueue() Statistics */ ! 3583: ulong exe_noerror; /* # ASC_NOERROR returns. */ ! 3584: ulong exe_busy; /* # ASC_BUSY returns. */ ! 3585: ulong exe_error; /* # ASC_ERROR returns. */ ! 3586: ulong exe_unknown; /* # unknown returns. */ ! 3587: /* Data Transfer Statistics */ ! 3588: ulong cont_cnt; /* # non-scatter-gather I/O requests received */ ! 3589: ulong cont_xfer; /* # contiguous transfer 512-bytes */ ! 3590: ulong sg_cnt; /* # scatter-gather I/O requests received */ ! 3591: ulong sg_elem; /* # scatter-gather elements */ ! 3592: ulong sg_xfer; /* # scatter-gather transfer 512-bytes */ ! 3593: }; ! 3594: #endif /* ADVANSYS_STATS */ ! 3595: ! 3596: /* ! 3597: * Request queuing structure ! 3598: */ ! 3599: typedef struct asc_queue { ! 3600: ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */ ! 3601: REQP q_first[ADV_MAX_TID+1]; /* first queued request */ ! 3602: REQP q_last[ADV_MAX_TID+1]; /* last queued request */ ! 3603: #ifdef ADVANSYS_STATS ! 3604: short q_cur_cnt[ADV_MAX_TID+1]; /* current queue count */ ! 3605: short q_max_cnt[ADV_MAX_TID+1]; /* maximum queue count */ ! 3606: ulong q_tot_cnt[ADV_MAX_TID+1]; /* total enqueue count */ ! 3607: ulong q_tot_tim[ADV_MAX_TID+1]; /* total time queued */ ! 3608: ushort q_max_tim[ADV_MAX_TID+1]; /* maximum time queued */ ! 3609: ushort q_min_tim[ADV_MAX_TID+1]; /* minimum time queued */ ! 3610: #endif /* ADVANSYS_STATS */ ! 3611: } asc_queue_t; ! 3612: ! 3613: /* ! 3614: * Adv Library Request Structures ! 3615: * ! 3616: * The following two se structures are used to process Wide Board requests. ! 3617: * One structure is needed for each command received from the Mid-Level SCSI ! 3618: * driver. ! 3619: * ! 3620: * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library ! 3621: * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the ! 3622: * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the ! 3623: * Mid-Level SCSI request structure. ! 3624: * ! 3625: * The adv_sgblk_t structure is used to handle requests that include ! 3626: * scatter-gather elements. ! 3627: */ ! 3628: typedef struct adv_sgblk { ! 3629: ADV_SG_BLOCK sg_block[ADV_NUM_SG_BLOCK + ADV_NUM_PAGE_CROSSING]; ! 3630: uchar align2[4]; /* Sgblock structure padding. */ ! 3631: struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */ ! 3632: } adv_sgblk_t; ! 3633: ! 3634: typedef struct adv_req { ! 3635: ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */ ! 3636: uchar align1[4]; /* Request structure padding. */ ! 3637: Scsi_Cmnd *cmndp; /* Mid-Level SCSI command pointer. */ ! 3638: adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */ ! 3639: struct adv_req *next_reqp; /* Next Request Structure. */ ! 3640: } adv_req_t; ! 3641: ! 3642: /* ! 3643: * Structure allocated for each board. ! 3644: * ! 3645: * This structure is allocated by scsi_register() at the end ! 3646: * of the 'Scsi_Host' structure starting at the 'hostdata' ! 3647: * field. It is guaranteed to be allocated from DMA-able memory. ! 3648: */ ! 3649: typedef struct asc_board { ! 3650: int id; /* Board Id */ ! 3651: uint flags; /* Board flags */ ! 3652: union { ! 3653: ASC_DVC_VAR asc_dvc_var; /* Narrow board */ ! 3654: ADV_DVC_VAR adv_dvc_var; /* Wide board */ ! 3655: } dvc_var; ! 3656: union { ! 3657: ASC_DVC_CFG asc_dvc_cfg; /* Narrow board */ ! 3658: ADV_DVC_CFG adv_dvc_cfg; /* Wide board */ ! 3659: } dvc_cfg; ! 3660: asc_queue_t active; /* Active command queue */ ! 3661: asc_queue_t waiting; /* Waiting command queue */ ! 3662: asc_queue_t done; /* Done command queue */ ! 3663: ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */ ! 3664: Scsi_Device *device[ADV_MAX_TID+1]; /* Mid-Level Scsi Device */ ! 3665: ushort reqcnt[ADV_MAX_TID+1]; /* Starvation request count */ ! 3666: #if ASC_QUEUE_FLOW_CONTROL ! 3667: ushort nerrcnt[ADV_MAX_TID+1]; /* No error request count */ ! 3668: #endif /* ASC_QUEUE_FLOW_CONTROL */ ! 3669: ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */ ! 3670: ushort queue_full_cnt[ADV_MAX_TID+1]; /* Queue full count */ ! 3671: union { ! 3672: ASCEEP_CONFIG asc_eep; /* Narrow EEPROM config. */ ! 3673: ADVEEP_CONFIG adv_eep; /* Wide EEPROM config. */ ! 3674: } eep_config; ! 3675: ulong last_reset; /* Saved last reset time */ ! 3676: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 3677: /* /proc/scsi/advansys/[0...] */ ! 3678: char *prtbuf; /* Statistics Print Buffer */ ! 3679: #endif /* version >= v1.3.0 */ ! 3680: #ifdef ADVANSYS_STATS ! 3681: struct asc_stats asc_stats; /* Board statistics */ ! 3682: #endif /* ADVANSYS_STATS */ ! 3683: /* ! 3684: * The following fields are used only for Narrow Boards. ! 3685: */ ! 3686: /* The following three structures must be in DMA-able memory. */ ! 3687: ASC_SCSI_REQ_Q scsireqq; ! 3688: ASC_CAP_INFO cap_info; ! 3689: ASC_SCSI_INQUIRY inquiry; ! 3690: uchar sdtr_data[ASC_MAX_TID+1]; /* SDTR information */ ! 3691: /* ! 3692: * The following fields are used only for Wide Boards. ! 3693: */ ! 3694: void *ioremap_addr; /* I/O Memory remap address. */ ! 3695: ushort ioport; /* I/O Port address. */ ! 3696: adv_req_t *orig_reqp; /* adv_req_t memory block. */ ! 3697: adv_req_t *adv_reqp; /* Request structures. */ ! 3698: adv_sgblk_t *orig_sgblkp; /* adv_sgblk_t memory block. */ ! 3699: adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */ ! 3700: ushort bios_signature; /* BIOS Signature. */ ! 3701: ushort bios_version; /* BIOS Version. */ ! 3702: ushort bios_codeseg; /* BIOS Code Segment. */ ! 3703: ushort bios_codelen; /* BIOS Code Segment Length. */ ! 3704: } asc_board_t; ! 3705: ! 3706: /* ! 3707: * PCI configuration structures ! 3708: */ ! 3709: typedef struct _PCI_DATA_ ! 3710: { ! 3711: uchar type; ! 3712: uchar bus; ! 3713: uchar slot; ! 3714: uchar func; ! 3715: uchar offset; ! 3716: } PCI_DATA; ! 3717: ! 3718: typedef struct _PCI_DEVICE_ ! 3719: { ! 3720: ushort vendorID; ! 3721: ushort deviceID; ! 3722: ushort slotNumber; ! 3723: ushort slotFound; ! 3724: uchar busNumber; ! 3725: uchar maxBusNumber; ! 3726: uchar devFunc; ! 3727: ushort startSlot; ! 3728: ushort endSlot; ! 3729: uchar bridge; ! 3730: uchar type; ! 3731: } PCI_DEVICE; ! 3732: ! 3733: typedef struct _PCI_CONFIG_SPACE_ ! 3734: { ! 3735: ushort vendorID; ! 3736: ushort deviceID; ! 3737: ushort command; ! 3738: ushort status; ! 3739: uchar revision; ! 3740: uchar classCode[3]; ! 3741: uchar cacheSize; ! 3742: uchar latencyTimer; ! 3743: uchar headerType; ! 3744: uchar bist; ! 3745: ulong baseAddress[6]; ! 3746: ushort reserved[4]; ! 3747: ulong optionRomAddr; ! 3748: ushort reserved2[4]; ! 3749: uchar irqLine; ! 3750: uchar irqPin; ! 3751: uchar minGnt; ! 3752: uchar maxLatency; ! 3753: } PCI_CONFIG_SPACE; ! 3754: ! 3755: ! 3756: /* ! 3757: * --- Driver Data ! 3758: */ ! 3759: ! 3760: /* Note: All driver global data should be initialized. */ ! 3761: ! 3762: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 3763: struct proc_dir_entry proc_scsi_advansys = ! 3764: { ! 3765: PROC_SCSI_ADVANSYS, /* unsigned short low_ino */ ! 3766: 8, /* unsigned short namelen */ ! 3767: "advansys", /* const char *name */ ! 3768: S_IFDIR | S_IRUGO | S_IXUGO, /* mode_t mode */ ! 3769: 2 /* nlink_t nlink */ ! 3770: }; ! 3771: #endif /* version >= v1.3.0 */ ! 3772: ! 3773: /* Number of boards detected in system. */ ! 3774: STATIC int asc_board_count = 0; ! 3775: STATIC struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { 0 }; ! 3776: ! 3777: /* Overrun buffer shared between all boards. */ ! 3778: STATIC uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 }; ! 3779: ! 3780: /* ! 3781: * Global structures required to issue a command. ! 3782: */ ! 3783: STATIC ASC_SCSI_Q asc_scsi_q = { { 0 } }; ! 3784: STATIC ASC_SG_HEAD asc_sg_head = { 0 }; ! 3785: ! 3786: /* List of supported bus types. */ ! 3787: STATIC ushort asc_bus[ASC_NUM_BUS] ASC_INITDATA = { ! 3788: ASC_IS_ISA, ! 3789: ASC_IS_VL, ! 3790: ASC_IS_EISA, ! 3791: ASC_IS_PCI, ! 3792: }; ! 3793: ! 3794: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) ! 3795: #ifdef ASC_CONFIG_PCI ! 3796: STATIC int pci_scan_method ASC_INITDATA = -1; ! 3797: #endif /* ASC_CONFIG_PCI */ ! 3798: #endif /* version < v2.1.93 */ ! 3799: ! 3800: /* ! 3801: * Used with the LILO 'advansys' option to eliminate or ! 3802: * limit I/O port probing at boot time, cf. advansys_setup(). ! 3803: */ ! 3804: STATIC int asc_iopflag = ASC_FALSE; ! 3805: STATIC int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 }; ! 3806: ! 3807: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0) ! 3808: /* ! 3809: * In kernels earlier than v1.3.0, kmalloc() does not work ! 3810: * during driver initialization. Therefore statically declare ! 3811: * 16 elements of each structure. v1.3.0 kernels will probably ! 3812: * not need any more than this number. ! 3813: */ ! 3814: uchar adv_req_buf[16 * sizeof(adv_req_t)] = { 0 }; ! 3815: uchar adv_sgblk_buf[16 * sizeof(adv_sgblk_t)] = { 0 }; ! 3816: #endif /* version >= v1,3,0 */ ! 3817: ! 3818: #ifdef ADVANSYS_DEBUG ! 3819: STATIC char * ! 3820: asc_bus_name[ASC_NUM_BUS] = { ! 3821: "ASC_IS_ISA", ! 3822: "ASC_IS_VL", ! 3823: "ASC_IS_EISA", ! 3824: "ASC_IS_PCI", ! 3825: }; ! 3826: ! 3827: STATIC int asc_dbglvl = 0; ! 3828: #endif /* ADVANSYS_DEBUG */ ! 3829: ! 3830: /* Declaration for Asc Library internal data referenced by driver. */ ! 3831: STATIC PortAddr _asc_def_iop_base[]; ! 3832: ! 3833: ! 3834: /* ! 3835: * --- Driver Function Prototypes ! 3836: * ! 3837: * advansys.h contains function prototypes for functions global to Linux. ! 3838: */ ! 3839: ! 3840: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 3841: STATIC int asc_proc_copy(off_t, off_t, char *, int , char *, int); ! 3842: #endif /* version >= v1.3.0 */ ! 3843: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70) ! 3844: STATIC void advansys_interrupt(int, struct pt_regs *); ! 3845: #else /* version >= v1.3.70 */ ! 3846: STATIC void advansys_interrupt(int, void *, struct pt_regs *); ! 3847: #endif /* version >= v1.3.70 */ ! 3848: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 3849: STATIC void advansys_select_queue_depths(struct Scsi_Host *, ! 3850: Scsi_Device *); ! 3851: #endif /* version >= v1.3.89 */ ! 3852: STATIC void advansys_command_done(Scsi_Cmnd *); ! 3853: STATIC void asc_scsi_done_list(Scsi_Cmnd *); ! 3854: STATIC int asc_execute_scsi_cmnd(Scsi_Cmnd *); ! 3855: STATIC int asc_build_req(asc_board_t *, Scsi_Cmnd *); ! 3856: STATIC int adv_build_req(asc_board_t *, Scsi_Cmnd *, ADV_SCSI_REQ_Q **); ! 3857: STATIC int adv_get_sglist(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *, Scsi_Cmnd *); ! 3858: STATIC void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *); ! 3859: STATIC void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); ! 3860: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) ! 3861: #ifdef ASC_CONFIG_PCI ! 3862: STATIC int asc_srch_pci_dev(PCI_DEVICE *); ! 3863: STATIC uchar asc_scan_method(void); ! 3864: STATIC int asc_pci_find_dev(PCI_DEVICE *); ! 3865: STATIC void asc_get_pci_cfg(PCI_DEVICE *, PCI_CONFIG_SPACE *); ! 3866: STATIC ushort asc_get_cfg_word(PCI_DATA *); ! 3867: STATIC uchar asc_get_cfg_byte(PCI_DATA *); ! 3868: STATIC void asc_put_cfg_byte(PCI_DATA *, uchar); ! 3869: #endif /* ASC_CONFIG_PCI */ ! 3870: #endif /* version < v2.1.93 */ ! 3871: STATIC void asc_enqueue(asc_queue_t *, REQP, int); ! 3872: STATIC REQP asc_dequeue(asc_queue_t *, int); ! 3873: STATIC REQP asc_dequeue_list(asc_queue_t *, REQP *, int); ! 3874: STATIC int asc_rmqueue(asc_queue_t *, REQP); ! 3875: STATIC int asc_isqueued(asc_queue_t *, REQP); ! 3876: STATIC void asc_execute_queue(asc_queue_t *); ! 3877: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 3878: STATIC int asc_prt_board_devices(struct Scsi_Host *, char *, int); ! 3879: STATIC int asc_prt_adv_bios(struct Scsi_Host *, char *, int); ! 3880: STATIC int asc_get_eeprom_string(ushort *serialnum, uchar *cp); ! 3881: STATIC int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int); ! 3882: STATIC int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int); ! 3883: STATIC int asc_prt_driver_conf(struct Scsi_Host *, char *, int); ! 3884: STATIC int asc_prt_asc_board_info(struct Scsi_Host *, char *, int); ! 3885: STATIC int asc_prt_adv_board_info(struct Scsi_Host *, char *, int); ! 3886: STATIC int asc_prt_line(char *, int, char *fmt, ...); ! 3887: #endif /* version >= v1.3.0 */ ! 3888: ! 3889: /* Declaration for Asc Library internal functions reference by driver. */ ! 3890: STATIC int AscFindSignature(PortAddr); ! 3891: STATIC ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); ! 3892: ! 3893: #ifdef ADVANSYS_STATS ! 3894: STATIC int asc_prt_board_stats(struct Scsi_Host *, char *, int); ! 3895: #endif /* ADVANSYS_STATS */ ! 3896: ! 3897: #ifdef ADVANSYS_DEBUG ! 3898: STATIC void asc_prt_scsi_host(struct Scsi_Host *); ! 3899: STATIC void asc_prt_scsi_cmnd(Scsi_Cmnd *); ! 3900: STATIC void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *); ! 3901: STATIC void asc_prt_asc_dvc_var(ASC_DVC_VAR *); ! 3902: STATIC void asc_prt_asc_scsi_q(ASC_SCSI_Q *); ! 3903: STATIC void asc_prt_asc_qdone_info(ASC_QDONE_INFO *); ! 3904: STATIC void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *); ! 3905: STATIC void asc_prt_adv_dvc_var(ADV_DVC_VAR *); ! 3906: STATIC void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *); ! 3907: STATIC void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *); ! 3908: STATIC void asc_prt_hex(char *f, uchar *, int); ! 3909: #endif /* ADVANSYS_DEBUG */ ! 3910: ! 3911: #ifdef ADVANSYS_ASSERT ! 3912: STATIC int interrupts_enabled(void); ! 3913: #endif /* ADVANSYS_ASSERT */ ! 3914: ! 3915: ! 3916: /* ! 3917: * --- Linux 'Scsi_Host_Template' and advansys_setup() Functions ! 3918: */ ! 3919: ! 3920: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 3921: /* ! 3922: * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)] ! 3923: * ! 3924: * *buffer: I/O buffer ! 3925: * **start: if inout == FALSE pointer into buffer where user read should start ! 3926: * offset: current offset into a /proc/scsi/advansys/[0...] file ! 3927: * length: length of buffer ! 3928: * hostno: Scsi_Host host_no ! 3929: * inout: TRUE - user is writing; FALSE - user is reading ! 3930: * ! 3931: * Return the number of bytes read from or written to a ! 3932: * /proc/scsi/advansys/[0...] file. ! 3933: * ! 3934: * Note: This function uses the per board buffer 'prtbuf' which is ! 3935: * allocated when the board is initialized in advansys_detect(). The ! 3936: * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is ! 3937: * used to write to the buffer. The way asc_proc_copy() is written ! 3938: * if 'prtbuf' is too small it will not be overwritten. Instead the ! 3939: * user just won't get all the available statistics. ! 3940: */ ! 3941: int ! 3942: advansys_proc_info(char *buffer, char **start, off_t offset, int length, ! 3943: int hostno, int inout) ! 3944: { ! 3945: struct Scsi_Host *shp; ! 3946: asc_board_t *boardp; ! 3947: int i; ! 3948: char *cp; ! 3949: int cplen; ! 3950: int cnt; ! 3951: int totcnt; ! 3952: int leftlen; ! 3953: char *curbuf; ! 3954: off_t advoffset; ! 3955: Scsi_Device *scd; ! 3956: ! 3957: ASC_DBG(1, "advansys_proc_info: begin\n"); ! 3958: ! 3959: /* ! 3960: * User write not supported. ! 3961: */ ! 3962: if (inout == TRUE) { ! 3963: return(-ENOSYS); ! 3964: } ! 3965: ! 3966: /* ! 3967: * User read of /proc/scsi/advansys/[0...] file. ! 3968: */ ! 3969: ! 3970: /* Find the specified board. */ ! 3971: for (i = 0; i < asc_board_count; i++) { ! 3972: if (asc_host[i]->host_no == hostno) { ! 3973: break; ! 3974: } ! 3975: } ! 3976: if (i == asc_board_count) { ! 3977: return(-ENOENT); ! 3978: } ! 3979: ! 3980: shp = asc_host[i]; ! 3981: boardp = ASC_BOARDP(shp); ! 3982: ! 3983: /* Copy read data starting at the beginning of the buffer. */ ! 3984: *start = buffer; ! 3985: curbuf = buffer; ! 3986: advoffset = 0; ! 3987: totcnt = 0; ! 3988: leftlen = length; ! 3989: ! 3990: /* ! 3991: * Get board configuration information. ! 3992: * ! 3993: * advansys_info() returns the board string from its own static buffer. ! 3994: */ ! 3995: cp = (char *) advansys_info(shp); ! 3996: strcat(cp, "\n"); ! 3997: cplen = strlen(cp); ! 3998: /* Copy board information. */ ! 3999: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); ! 4000: totcnt += cnt; ! 4001: leftlen -= cnt; ! 4002: if (leftlen == 0) { ! 4003: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); ! 4004: return totcnt; ! 4005: } ! 4006: advoffset += cplen; ! 4007: curbuf += cnt; ! 4008: ! 4009: /* ! 4010: * Display Wide Board BIOS Information. ! 4011: */ ! 4012: if (ASC_WIDE_BOARD(boardp)) { ! 4013: cp = boardp->prtbuf; ! 4014: cplen = asc_prt_adv_bios(shp, cp, ASC_PRTBUF_SIZE); ! 4015: ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); ! 4016: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); ! 4017: totcnt += cnt; ! 4018: leftlen -= cnt; ! 4019: if (leftlen == 0) { ! 4020: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); ! 4021: return totcnt; ! 4022: } ! 4023: advoffset += cplen; ! 4024: curbuf += cnt; ! 4025: } ! 4026: ! 4027: /* ! 4028: * Display driver information for each device attached to the board. ! 4029: */ ! 4030: cp = boardp->prtbuf; ! 4031: cplen = asc_prt_board_devices(shp, cp, ASC_PRTBUF_SIZE); ! 4032: ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); ! 4033: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); ! 4034: totcnt += cnt; ! 4035: leftlen -= cnt; ! 4036: if (leftlen == 0) { ! 4037: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); ! 4038: return totcnt; ! 4039: } ! 4040: advoffset += cplen; ! 4041: curbuf += cnt; ! 4042: ! 4043: /* ! 4044: * Display target driver information for each device attached ! 4045: * to the board. ! 4046: */ ! 4047: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,75) ! 4048: for (scd = scsi_devices; scd; scd = scd->next) ! 4049: #else /* version >= v2.1.75 */ ! 4050: for (scd = shp->host_queue; scd; scd = scd->next) ! 4051: #endif /* version >= v2.1.75 */ ! 4052: { ! 4053: if (scd->host == shp) { ! 4054: cp = boardp->prtbuf; ! 4055: /* ! 4056: * Note: If proc_print_scsidevice() writes more than ! 4057: * ASC_PRTBUF_SIZE bytes, it will overrun 'prtbuf'. ! 4058: */ ! 4059: proc_print_scsidevice(scd, cp, &cplen, 0); ! 4060: ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); ! 4061: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); ! 4062: totcnt += cnt; ! 4063: leftlen -= cnt; ! 4064: if (leftlen == 0) { ! 4065: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); ! 4066: return totcnt; ! 4067: } ! 4068: advoffset += cplen; ! 4069: curbuf += cnt; ! 4070: } ! 4071: } ! 4072: ! 4073: /* ! 4074: * Display EEPROM configuration for the board. ! 4075: */ ! 4076: cp = boardp->prtbuf; ! 4077: if (ASC_NARROW_BOARD(boardp)) { ! 4078: cplen = asc_prt_asc_board_eeprom(shp, cp, ASC_PRTBUF_SIZE); ! 4079: } else { ! 4080: cplen = asc_prt_adv_board_eeprom(shp, cp, ASC_PRTBUF_SIZE); ! 4081: } ! 4082: ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); ! 4083: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); ! 4084: totcnt += cnt; ! 4085: leftlen -= cnt; ! 4086: if (leftlen == 0) { ! 4087: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); ! 4088: return totcnt; ! 4089: } ! 4090: advoffset += cplen; ! 4091: curbuf += cnt; ! 4092: ! 4093: /* ! 4094: * Display driver configuration and information for the board. ! 4095: */ ! 4096: cp = boardp->prtbuf; ! 4097: cplen = asc_prt_driver_conf(shp, cp, ASC_PRTBUF_SIZE); ! 4098: ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); ! 4099: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); ! 4100: totcnt += cnt; ! 4101: leftlen -= cnt; ! 4102: if (leftlen == 0) { ! 4103: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); ! 4104: return totcnt; ! 4105: } ! 4106: advoffset += cplen; ! 4107: curbuf += cnt; ! 4108: ! 4109: #ifdef ADVANSYS_STATS ! 4110: /* ! 4111: * Display driver statistics for the board. ! 4112: */ ! 4113: cp = boardp->prtbuf; ! 4114: cplen = asc_prt_board_stats(shp, cp, ASC_PRTBUF_SIZE); ! 4115: ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); ! 4116: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); ! 4117: totcnt += cnt; ! 4118: leftlen -= cnt; ! 4119: if (leftlen == 0) { ! 4120: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); ! 4121: return totcnt; ! 4122: } ! 4123: advoffset += cplen; ! 4124: curbuf += cnt; ! 4125: #endif /* ADVANSYS_STATS */ ! 4126: ! 4127: /* ! 4128: * Display Asc Library dynamic configuration information ! 4129: * for the board. ! 4130: */ ! 4131: cp = boardp->prtbuf; ! 4132: if (ASC_NARROW_BOARD(boardp)) { ! 4133: cplen = asc_prt_asc_board_info(shp, cp, ASC_PRTBUF_SIZE); ! 4134: } else { ! 4135: cplen = asc_prt_adv_board_info(shp, cp, ASC_PRTBUF_SIZE); ! 4136: } ! 4137: ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); ! 4138: cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); ! 4139: totcnt += cnt; ! 4140: leftlen -= cnt; ! 4141: if (leftlen == 0) { ! 4142: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); ! 4143: return totcnt; ! 4144: } ! 4145: advoffset += cplen; ! 4146: curbuf += cnt; ! 4147: ! 4148: ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); ! 4149: ! 4150: return totcnt; ! 4151: } ! 4152: #endif /* version >= v1.3.0 */ ! 4153: ! 4154: /* ! 4155: * advansys_detect() ! 4156: * ! 4157: * Detect function for AdvanSys adapters. ! 4158: * ! 4159: * Argument is a pointer to the host driver's scsi_hosts entry. ! 4160: * ! 4161: * Return number of adapters found. ! 4162: * ! 4163: * Note: Because this function is called during system initialization ! 4164: * it must not call SCSI mid-level functions including scsi_malloc() ! 4165: * and scsi_free(). ! 4166: */ ! 4167: ASC_INITFUNC( ! 4168: int ! 4169: advansys_detect(Scsi_Host_Template *tpnt) ! 4170: ) ! 4171: { ! 4172: static int detect_called = ASC_FALSE; ! 4173: int iop; ! 4174: int bus; ! 4175: struct Scsi_Host *shp; ! 4176: asc_board_t *boardp; ! 4177: ASC_DVC_VAR *asc_dvc_varp = NULL; ! 4178: ADV_DVC_VAR *adv_dvc_varp = NULL; ! 4179: int ioport = 0; ! 4180: int share_irq = FALSE; ! 4181: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) ! 4182: #ifdef ASC_CONFIG_PCI ! 4183: PCI_DEVICE pciDevice; ! 4184: PCI_CONFIG_SPACE pciConfig; ! 4185: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 4186: unsigned long pci_memory_address; ! 4187: #endif /* version >= v1,3,0 */ ! 4188: #endif /* ASC_CONFIG_PCI */ ! 4189: #else /* version >= v2.1.93 */ ! 4190: #ifdef CONFIG_PCI ! 4191: struct pci_dev *pci_devp = NULL; ! 4192: int pci_device_id_cnt = 0; ! 4193: unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = { ! 4194: ASC_PCI_DEVICE_ID_1100, ! 4195: ASC_PCI_DEVICE_ID_1200, ! 4196: ASC_PCI_DEVICE_ID_1300, ! 4197: ASC_PCI_DEVICE_ID_2300 ! 4198: }; ! 4199: unsigned long pci_memory_address; ! 4200: #endif /* CONFIG_PCI */ ! 4201: #endif /* version >= v2.1.93 */ ! 4202: int warn_code, err_code; ! 4203: int ret; ! 4204: ! 4205: if (detect_called == ASC_FALSE) { ! 4206: detect_called = ASC_TRUE; ! 4207: } else { ! 4208: printk("AdvanSys SCSI: advansys_detect() multiple calls ignored\n"); ! 4209: return 0; ! 4210: } ! 4211: ! 4212: ASC_DBG(1, "advansys_detect: begin\n"); ! 4213: ! 4214: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 4215: tpnt->proc_dir = &proc_scsi_advansys; ! 4216: #endif /* version >= v1.3.0 */ ! 4217: ! 4218: asc_board_count = 0; ! 4219: ! 4220: /* ! 4221: * If I/O port probing has been modified, then verify and ! 4222: * clean-up the 'asc_ioport' list. ! 4223: */ ! 4224: if (asc_iopflag == ASC_TRUE) { ! 4225: for (ioport = 0; ioport < ASC_NUM_IOPORT_PROBE; ioport++) { ! 4226: ASC_DBG2(1, "advansys_detect: asc_ioport[%d] %x\n", ! 4227: ioport, asc_ioport[ioport]); ! 4228: if (asc_ioport[ioport] != 0) { ! 4229: for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; iop++) { ! 4230: if (_asc_def_iop_base[iop] == asc_ioport[ioport]) { ! 4231: break; ! 4232: } ! 4233: } ! 4234: if (iop == ASC_IOADR_TABLE_MAX_IX) { ! 4235: printk( ! 4236: "AdvanSys SCSI: specified I/O Port 0x%X is invalid\n", ! 4237: asc_ioport[ioport]); ! 4238: asc_ioport[ioport] = 0; ! 4239: } ! 4240: } ! 4241: } ! 4242: ioport = 0; ! 4243: } ! 4244: ! 4245: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) ! 4246: #ifdef ASC_CONFIG_PCI ! 4247: memset(&pciDevice, 0, sizeof(PCI_DEVICE)); ! 4248: memset(&pciConfig, 0, sizeof(PCI_CONFIG_SPACE)); ! 4249: pciDevice.maxBusNumber = PCI_MAX_BUS; ! 4250: pciDevice.endSlot = PCI_MAX_SLOT; ! 4251: #endif /* ASC_CONFIG_PCI */ ! 4252: #endif /* version < v2.1.93 */ ! 4253: ! 4254: for (bus = 0; bus < ASC_NUM_BUS; bus++) { ! 4255: ! 4256: ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n", ! 4257: bus, asc_bus_name[bus]); ! 4258: iop = 0; ! 4259: ! 4260: while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) { ! 4261: ! 4262: ASC_DBG1(2, "advansys_detect: asc_board_count %d\n", ! 4263: asc_board_count); ! 4264: ! 4265: switch (asc_bus[bus]) { ! 4266: case ASC_IS_ISA: ! 4267: case ASC_IS_VL: ! 4268: if (asc_iopflag == ASC_FALSE) { ! 4269: iop = AscSearchIOPortAddr(iop, asc_bus[bus]); ! 4270: } else { ! 4271: /* ! 4272: * ISA and VL I/O port scanning has either been ! 4273: * eliminated or limited to selected ports on ! 4274: * the LILO command line, /etc/lilo.conf, or ! 4275: * by setting variables when the module was loaded. ! 4276: */ ! 4277: ASC_DBG(1, "advansys_detect: I/O port scanning modified\n"); ! 4278: ioport_try_again: ! 4279: iop = 0; ! 4280: for (; ioport < ASC_NUM_IOPORT_PROBE; ioport++) { ! 4281: if ((iop = asc_ioport[ioport]) != 0) { ! 4282: break; ! 4283: } ! 4284: } ! 4285: if (iop) { ! 4286: ASC_DBG1(1, "advansys_detect: probing I/O port %x...\n", ! 4287: iop); ! 4288: if (check_region(iop, ASC_IOADR_GAP) != 0) { ! 4289: printk( ! 4290: "AdvanSys SCSI: specified I/O Port 0x%X is busy\n", iop); ! 4291: /* Don't try this I/O port twice. */ ! 4292: asc_ioport[ioport] = 0; ! 4293: goto ioport_try_again; ! 4294: } else if (AscFindSignature(iop) == ASC_FALSE) { ! 4295: printk( ! 4296: "AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", iop); ! 4297: /* Don't try this I/O port twice. */ ! 4298: asc_ioport[ioport] = 0; ! 4299: goto ioport_try_again; ! 4300: } else { ! 4301: /* ! 4302: * If this isn't an ISA board, then it must be ! 4303: * a VL board. If currently looking an ISA ! 4304: * board is being looked for then try for ! 4305: * another ISA board in 'asc_ioport'. ! 4306: */ ! 4307: if (asc_bus[bus] == ASC_IS_ISA && ! 4308: (AscGetChipVersion(iop, ASC_IS_ISA) & ! 4309: ASC_CHIP_VER_ISA_BIT) == 0) { ! 4310: /* ! 4311: * Don't clear 'asc_ioport[ioport]'. Try ! 4312: * this board again for VL. Increment ! 4313: * 'ioport' past this board. ! 4314: */ ! 4315: ioport++; ! 4316: goto ioport_try_again; ! 4317: } ! 4318: } ! 4319: /* ! 4320: * This board appears good, don't try the I/O port ! 4321: * again by clearing its value. Increment 'ioport' ! 4322: * for the next iteration. ! 4323: */ ! 4324: asc_ioport[ioport++] = 0; ! 4325: } ! 4326: } ! 4327: break; ! 4328: ! 4329: case ASC_IS_EISA: ! 4330: iop = AscSearchIOPortAddr(iop, asc_bus[bus]); ! 4331: break; ! 4332: ! 4333: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) ! 4334: #ifdef ASC_CONFIG_PCI ! 4335: case ASC_IS_PCI: ! 4336: if (asc_srch_pci_dev(&pciDevice) != PCI_DEVICE_FOUND) { ! 4337: iop = 0; ! 4338: } else { ! 4339: ASC_DBG2(2, ! 4340: "advansys_detect: slotFound %d, busNumber %d\n", ! 4341: pciDevice.slotFound, pciDevice.busNumber); ! 4342: asc_get_pci_cfg(&pciDevice, &pciConfig); ! 4343: iop = pciConfig.baseAddress[0] & PCI_IOADDRESS_MASK; ! 4344: ASC_DBG2(1, ! 4345: "advansys_detect: vendorID %X, deviceID %X\n", ! 4346: pciConfig.vendorID, pciConfig.deviceID); ! 4347: ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n", ! 4348: iop, pciConfig.irqLine); ! 4349: } ! 4350: break; ! 4351: #endif /* ASC_CONFIG_PCI */ ! 4352: #else /* version >= v2.1.93 */ ! 4353: #ifdef CONFIG_PCI ! 4354: case ASC_IS_PCI: ! 4355: while (pci_device_id_cnt < ASC_PCI_DEVICE_ID_CNT) { ! 4356: if ((pci_devp = pci_find_device(ASC_PCI_VENDORID, ! 4357: pci_device_id[pci_device_id_cnt], pci_devp)) == NULL) { ! 4358: pci_device_id_cnt++; ! 4359: } else { ! 4360: break; ! 4361: } ! 4362: } ! 4363: if (pci_devp == NULL) { ! 4364: iop = 0; ! 4365: } else { ! 4366: ASC_DBG2(2, ! 4367: "advansys_detect: devfn %d, bus number %d\n", ! 4368: pci_devp->devfn, pci_devp->bus->number); ! 4369: iop = pci_devp->base_address[0] & PCI_IOADDRESS_MASK; ! 4370: ASC_DBG2(1, ! 4371: "advansys_detect: vendorID %X, deviceID %X\n", ! 4372: pci_devp->vendor, pci_devp->device); ! 4373: ASC_DBG2(2, "advansys_detect: iop %X, irqLine %d\n", ! 4374: iop, pci_devp->irq); ! 4375: } ! 4376: break; ! 4377: #endif /* CONFIG_PCI */ ! 4378: #endif /* version >= v2.1.93 */ ! 4379: ! 4380: default: ! 4381: ASC_PRINT1("advansys_detect: unknown bus type: %d\n", ! 4382: asc_bus[bus]); ! 4383: break; ! 4384: } ! 4385: ASC_DBG1(1, "advansys_detect: iop %x\n", iop); ! 4386: ! 4387: /* ! 4388: * Adapter not found, try next bus type. ! 4389: */ ! 4390: if (iop == 0) { ! 4391: break; ! 4392: } ! 4393: ! 4394: /* ! 4395: * Adapter found. ! 4396: * ! 4397: * Register the adapter, get its configuration, and ! 4398: * initialize it. ! 4399: */ ! 4400: ASC_DBG(2, "advansys_detect: scsi_register()\n"); ! 4401: shp = scsi_register(tpnt, sizeof(asc_board_t)); ! 4402: ! 4403: /* Save a pointer to the Scsi_host of each board found. */ ! 4404: asc_host[asc_board_count++] = shp; ! 4405: ! 4406: /* Initialize private per board data */ ! 4407: boardp = ASC_BOARDP(shp); ! 4408: memset(boardp, 0, sizeof(asc_board_t)); ! 4409: boardp->id = asc_board_count - 1; ! 4410: ! 4411: /* ! 4412: * Handle both narrow and wide boards. ! 4413: * ! 4414: * If a Wide board was detected, set the board structure ! 4415: * wide board flag. Set-up the board structure based on ! 4416: * the board type. ! 4417: */ ! 4418: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) ! 4419: #ifdef ASC_CONFIG_PCI ! 4420: if (asc_bus[bus] == ASC_IS_PCI && ! 4421: pciConfig.deviceID == ASC_PCI_DEVICE_ID_2300) { ! 4422: boardp->flags |= ASC_IS_WIDE_BOARD; ! 4423: } ! 4424: #endif /* ASC_CONFIG_PCI */ ! 4425: #else /* version >= v2.1.93 */ ! 4426: #ifdef CONFIG_PCI ! 4427: if (asc_bus[bus] == ASC_IS_PCI && ! 4428: pci_devp->device == ASC_PCI_DEVICE_ID_2300) { ! 4429: boardp->flags |= ASC_IS_WIDE_BOARD; ! 4430: } ! 4431: #endif /* CONFIG_PCI */ ! 4432: #endif /* version >= v2.1.93 */ ! 4433: ! 4434: if (ASC_NARROW_BOARD(boardp)) { ! 4435: ASC_DBG(1, "advansys_detect: narrow board\n"); ! 4436: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; ! 4437: asc_dvc_varp->bus_type = asc_bus[bus]; ! 4438: asc_dvc_varp->drv_ptr = (ulong) boardp; ! 4439: asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg; ! 4440: asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0]; ! 4441: asc_dvc_varp->iop_base = iop; ! 4442: asc_dvc_varp->isr_callback = (Ptr2Func) asc_isr_callback; ! 4443: } else { ! 4444: ASC_DBG(1, "advansys_detect: wide board\n"); ! 4445: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; ! 4446: adv_dvc_varp->drv_ptr = (ulong) boardp; ! 4447: adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg; ! 4448: adv_dvc_varp->isr_callback = (Ptr2Func) adv_isr_callback; ! 4449: ! 4450: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0) ! 4451: adv_dvc_varp->iop_base = iop; ! 4452: #else /* version >= v1,3,0 */ ! 4453: /* ! 4454: * Map the board's registers into virtual memory for ! 4455: * PCI slave access. Only memory accesses are used to ! 4456: * access the board's registers. ! 4457: * ! 4458: * Note: The PCI register base address is not always ! 4459: * page aligned, but the address passed to ioremap() ! 4460: * must be page aligned. It is guaranteed that the ! 4461: * PCI register base address will not cross a page ! 4462: * boundary. ! 4463: */ ! 4464: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) ! 4465: #ifdef ASC_CONFIG_PCI ! 4466: pci_memory_address = pciConfig.baseAddress[1]; ! 4467: if ((boardp->ioremap_addr = ! 4468: ioremap(pci_memory_address & PAGE_MASK, ! 4469: PAGE_SIZE)) == 0) { ! 4470: ASC_PRINT3( ! 4471: "advansys_detect: board %d: ioremap(%lx, %d) returned NULL\n", ! 4472: boardp->id, pci_memory_address, ADV_CONDOR_IOLEN); ! 4473: scsi_unregister(shp); ! 4474: asc_board_count--; ! 4475: continue; ! 4476: } ! 4477: adv_dvc_varp->iop_base = (AdvPortAddr) ! 4478: (boardp->ioremap_addr + ! 4479: (pci_memory_address - (pci_memory_address & PAGE_MASK))); ! 4480: #endif /* ASC_CONFIG_PCI */ ! 4481: #else /* version >= v2.1.93 */ ! 4482: #ifdef CONFIG_PCI ! 4483: pci_memory_address = pci_devp->base_address[1]; ! 4484: if ((boardp->ioremap_addr = ! 4485: ioremap(pci_memory_address & PAGE_MASK, ! 4486: PAGE_SIZE)) == 0) { ! 4487: ASC_PRINT3( ! 4488: "advansys_detect: board %d: ioremap(%lx, %d) returned NULL\n", ! 4489: boardp->id, pci_memory_address, ADV_CONDOR_IOLEN); ! 4490: scsi_unregister(shp); ! 4491: asc_board_count--; ! 4492: continue; ! 4493: } ! 4494: adv_dvc_varp->iop_base = (AdvPortAddr) ! 4495: (boardp->ioremap_addr + ! 4496: (pci_memory_address - (pci_memory_address & PAGE_MASK))); ! 4497: #endif /* CONFIG_PCI */ ! 4498: #endif /* version >= v2.1.93 */ ! 4499: #endif /* version >= v1,3,0 */ ! 4500: ! 4501: /* ! 4502: * Even though it isn't used to access the board in ! 4503: * kernels greater than or equal to v1.3.0, save ! 4504: * the I/O Port address so that it can be reported and ! 4505: * displayed. ! 4506: */ ! 4507: boardp->ioport = iop; ! 4508: } ! 4509: ! 4510: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 4511: /* ! 4512: * Allocate buffer for printing information from ! 4513: * /proc/scsi/advansys/[0...]. ! 4514: */ ! 4515: if ((boardp->prtbuf = ! 4516: kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) { ! 4517: ASC_PRINT3( ! 4518: "advansys_detect: board %d: kmalloc(%d, %d) returned NULL\n", ! 4519: boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC); ! 4520: scsi_unregister(shp); ! 4521: asc_board_count--; ! 4522: continue; ! 4523: } ! 4524: #endif /* version >= v1.3.0 */ ! 4525: ! 4526: if (ASC_NARROW_BOARD(boardp)) { ! 4527: /* ! 4528: * Set the board bus type and PCI IRQ before ! 4529: * calling AscInitGetConfig(). ! 4530: */ ! 4531: switch (asc_dvc_varp->bus_type) { ! 4532: case ASC_IS_ISA: ! 4533: shp->unchecked_isa_dma = TRUE; ! 4534: share_irq = FALSE; ! 4535: break; ! 4536: case ASC_IS_VL: ! 4537: shp->unchecked_isa_dma = FALSE; ! 4538: share_irq = FALSE; ! 4539: break; ! 4540: case ASC_IS_EISA: ! 4541: shp->unchecked_isa_dma = FALSE; ! 4542: share_irq = TRUE; ! 4543: break; ! 4544: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) ! 4545: #ifdef ASC_CONFIG_PCI ! 4546: case ASC_IS_PCI: ! 4547: shp->irq = asc_dvc_varp->irq_no = pciConfig.irqLine; ! 4548: asc_dvc_varp->cfg->pci_device_id = pciConfig.deviceID; ! 4549: asc_dvc_varp->cfg->pci_slot_info = ! 4550: ASC_PCI_MKID(pciDevice.busNumber, ! 4551: pciDevice.slotFound, ! 4552: pciDevice.devFunc); ! 4553: shp->unchecked_isa_dma = FALSE; ! 4554: share_irq = TRUE; ! 4555: break; ! 4556: #endif /* ASC_CONFIG_PCI */ ! 4557: #else /* version >= v2.1.93 */ ! 4558: #ifdef CONFIG_PCI ! 4559: case ASC_IS_PCI: ! 4560: shp->irq = asc_dvc_varp->irq_no = pci_devp->irq; ! 4561: asc_dvc_varp->cfg->pci_device_id = pci_devp->device; ! 4562: asc_dvc_varp->cfg->pci_slot_info = ! 4563: ASC_PCI_MKID(pci_devp->bus->number, ! 4564: PCI_SLOT(pci_devp->devfn), ! 4565: PCI_FUNC(pci_devp->devfn)); ! 4566: shp->unchecked_isa_dma = FALSE; ! 4567: share_irq = TRUE; ! 4568: break; ! 4569: #endif /* CONFIG_PCI */ ! 4570: #endif /* version >= v2.1.93 */ ! 4571: default: ! 4572: ASC_PRINT2( ! 4573: "advansys_detect: board %d: unknown adapter type: %d\n", ! 4574: boardp->id, asc_dvc_varp->bus_type); ! 4575: shp->unchecked_isa_dma = TRUE; ! 4576: share_irq = FALSE; ! 4577: break; ! 4578: } ! 4579: } else { ! 4580: /* ! 4581: * For Wide boards set PCI information before calling ! 4582: * AdvInitGetConfig(). ! 4583: */ ! 4584: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) ! 4585: #ifdef ASC_CONFIG_PCI ! 4586: shp->irq = adv_dvc_varp->irq_no = pciConfig.irqLine; ! 4587: adv_dvc_varp->cfg->pci_device_id = pciConfig.deviceID; ! 4588: adv_dvc_varp->cfg->pci_slot_info = ! 4589: ASC_PCI_MKID(pciDevice.busNumber, ! 4590: pciDevice.slotFound, ! 4591: pciDevice.devFunc); ! 4592: shp->unchecked_isa_dma = FALSE; ! 4593: share_irq = TRUE; ! 4594: #endif /* ASC_CONFIG_PCI */ ! 4595: #else /* version >= v2.1.93 */ ! 4596: #ifdef CONFIG_PCI ! 4597: shp->irq = adv_dvc_varp->irq_no = pci_devp->irq; ! 4598: adv_dvc_varp->cfg->pci_device_id = pci_devp->device; ! 4599: adv_dvc_varp->cfg->pci_slot_info = ! 4600: ASC_PCI_MKID(pci_devp->bus->number, ! 4601: PCI_SLOT(pci_devp->devfn), ! 4602: PCI_FUNC(pci_devp->devfn)); ! 4603: shp->unchecked_isa_dma = FALSE; ! 4604: share_irq = TRUE; ! 4605: #endif /* CONFIG_PCI */ ! 4606: #endif /* version >= v2.1.93 */ ! 4607: } ! 4608: ! 4609: /* ! 4610: * Read the board configuration. ! 4611: */ ! 4612: if (ASC_NARROW_BOARD(boardp)) { ! 4613: /* ! 4614: * NOTE: AscInitGetConfig() may change the board's ! 4615: * bus_type value. The asc_bus[bus] value should no ! 4616: * longer be used. If the bus_type field must be ! 4617: * referenced only use the bit-wise AND operator "&". ! 4618: */ ! 4619: ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n"); ! 4620: switch(ret = AscInitGetConfig(asc_dvc_varp)) { ! 4621: case 0: /* No error */ ! 4622: break; ! 4623: case ASC_WARN_IO_PORT_ROTATE: ! 4624: ASC_PRINT1( ! 4625: "AscInitGetConfig: board %d: I/O port address modified\n", ! 4626: boardp->id); ! 4627: break; ! 4628: case ASC_WARN_AUTO_CONFIG: ! 4629: ASC_PRINT1( ! 4630: "AscInitGetConfig: board %d: I/O port increment switch enabled\n", ! 4631: boardp->id); ! 4632: break; ! 4633: case ASC_WARN_EEPROM_CHKSUM: ! 4634: ASC_PRINT1( ! 4635: "AscInitGetConfig: board %d: EEPROM checksum error\n", ! 4636: boardp->id); ! 4637: break; ! 4638: case ASC_WARN_IRQ_MODIFIED: ! 4639: ASC_PRINT1( ! 4640: "AscInitGetConfig: board %d: IRQ modified\n", ! 4641: boardp->id); ! 4642: break; ! 4643: case ASC_WARN_CMD_QNG_CONFLICT: ! 4644: ASC_PRINT1( ! 4645: "AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n", ! 4646: boardp->id); ! 4647: break; ! 4648: default: ! 4649: ASC_PRINT2( ! 4650: "AscInitGetConfig: board %d: unknown warning: %x\n", ! 4651: boardp->id, ret); ! 4652: break; ! 4653: } ! 4654: if ((err_code = asc_dvc_varp->err_code) != 0) { ! 4655: ASC_PRINT3( ! 4656: "AscInitGetConfig: board %d error: init_state %x, err_code %x\n", ! 4657: boardp->id, asc_dvc_varp->init_state, ! 4658: asc_dvc_varp->err_code); ! 4659: } ! 4660: } else { ! 4661: ASC_DBG(2, "advansys_detect: AdvInitGetConfig()\n"); ! 4662: if ((ret = AdvInitGetConfig(adv_dvc_varp)) != 0) { ! 4663: ASC_PRINT2("AdvInitGetConfig: board %d: warning: %x\n", ! 4664: boardp->id, ret); ! 4665: } ! 4666: if ((err_code = adv_dvc_varp->err_code) != 0) { ! 4667: ASC_PRINT2( ! 4668: "AdvInitGetConfig: board %d error: err_code %x\n", ! 4669: boardp->id, adv_dvc_varp->err_code); ! 4670: } ! 4671: } ! 4672: ! 4673: if (err_code != 0) { ! 4674: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 4675: kfree(boardp->prtbuf); ! 4676: #endif /* version >= v1.3.0 */ ! 4677: scsi_unregister(shp); ! 4678: asc_board_count--; ! 4679: continue; ! 4680: } ! 4681: ! 4682: /* ! 4683: * Save the EEPROM configuration so that it can be displayed ! 4684: * from /proc/scsi/advansys/[0...]. ! 4685: */ ! 4686: if (ASC_NARROW_BOARD(boardp)) { ! 4687: ! 4688: ASCEEP_CONFIG *ep; ! 4689: ! 4690: /* ! 4691: * Set the adapter's target id bit in the 'init_tidmask' field. ! 4692: */ ! 4693: boardp->init_tidmask |= ! 4694: ADV_TID_TO_TIDMASK(asc_dvc_varp->cfg->chip_scsi_id); ! 4695: ! 4696: /* ! 4697: * Save EEPROM settings for the board. ! 4698: */ ! 4699: ep = &boardp->eep_config.asc_eep; ! 4700: ! 4701: ep->init_sdtr = asc_dvc_varp->cfg->sdtr_enable; ! 4702: ep->disc_enable = asc_dvc_varp->cfg->disc_enable; ! 4703: ep->use_cmd_qng = asc_dvc_varp->cfg->cmd_qng_enabled; ! 4704: ep->isa_dma_speed = asc_dvc_varp->cfg->isa_dma_speed; ! 4705: ep->start_motor = asc_dvc_varp->start_motor; ! 4706: ep->cntl = asc_dvc_varp->dvc_cntl; ! 4707: ep->no_scam = asc_dvc_varp->no_scam; ! 4708: ep->max_total_qng = asc_dvc_varp->max_total_qng; ! 4709: ep->chip_scsi_id = asc_dvc_varp->cfg->chip_scsi_id; ! 4710: /* 'max_tag_qng' is set to the same value for every device. */ ! 4711: ep->max_tag_qng = asc_dvc_varp->cfg->max_tag_qng[0]; ! 4712: ep->adapter_info[0] = asc_dvc_varp->cfg->adapter_info[0]; ! 4713: ep->adapter_info[1] = asc_dvc_varp->cfg->adapter_info[1]; ! 4714: ep->adapter_info[2] = asc_dvc_varp->cfg->adapter_info[2]; ! 4715: ep->adapter_info[3] = asc_dvc_varp->cfg->adapter_info[3]; ! 4716: ep->adapter_info[4] = asc_dvc_varp->cfg->adapter_info[4]; ! 4717: ep->adapter_info[5] = asc_dvc_varp->cfg->adapter_info[5]; ! 4718: ep->adapter_info[6] = asc_dvc_varp->cfg->adapter_info[6]; ! 4719: ! 4720: /* ! 4721: * Modify board configuration. ! 4722: */ ! 4723: ASC_DBG(2, "advansys_detect: AscInitSetConfig()\n"); ! 4724: switch (ret = AscInitSetConfig(asc_dvc_varp)) { ! 4725: case 0: /* No error. */ ! 4726: break; ! 4727: case ASC_WARN_IO_PORT_ROTATE: ! 4728: ASC_PRINT1( ! 4729: "AscInitSetConfig: board %d: I/O port address modified\n", ! 4730: boardp->id); ! 4731: break; ! 4732: case ASC_WARN_AUTO_CONFIG: ! 4733: ASC_PRINT1( ! 4734: "AscInitSetConfig: board %d: I/O port increment switch enabled\n", ! 4735: boardp->id); ! 4736: break; ! 4737: case ASC_WARN_EEPROM_CHKSUM: ! 4738: ASC_PRINT1( ! 4739: "AscInitSetConfig: board %d: EEPROM checksum error\n", ! 4740: boardp->id); ! 4741: break; ! 4742: case ASC_WARN_IRQ_MODIFIED: ! 4743: ASC_PRINT1( ! 4744: "AscInitSetConfig: board %d: IRQ modified\n", ! 4745: boardp->id); ! 4746: break; ! 4747: case ASC_WARN_CMD_QNG_CONFLICT: ! 4748: ASC_PRINT1( ! 4749: "AscInitSetConfig: board %d: tag queuing w/o disconnects\n", ! 4750: boardp->id); ! 4751: break; ! 4752: default: ! 4753: ASC_PRINT2( ! 4754: "AscInitSetConfig: board %d: unknown warning: %x\n", ! 4755: boardp->id, ret); ! 4756: break; ! 4757: } ! 4758: if (asc_dvc_varp->err_code != 0) { ! 4759: ASC_PRINT3( ! 4760: "AscInitSetConfig: board %d error: init_state %x, err_code %x\n", ! 4761: boardp->id, asc_dvc_varp->init_state, ! 4762: asc_dvc_varp->err_code); ! 4763: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 4764: kfree(boardp->prtbuf); ! 4765: #endif /* version >= v1.3.0 */ ! 4766: scsi_unregister(shp); ! 4767: asc_board_count--; ! 4768: continue; ! 4769: } ! 4770: ! 4771: /* ! 4772: * Finish initializing the 'Scsi_Host' structure. ! 4773: */ ! 4774: /* AscInitSetConfig() will set the IRQ for non-PCI boards. */ ! 4775: if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) { ! 4776: shp->irq = asc_dvc_varp->irq_no; ! 4777: } ! 4778: } else { ! 4779: ! 4780: ADVEEP_CONFIG *ep; ! 4781: ! 4782: /* ! 4783: * Save Wide EEP Configuration Information. ! 4784: */ ! 4785: ep = &boardp->eep_config.adv_eep; ! 4786: ! 4787: ep->adapter_scsi_id = adv_dvc_varp->chip_scsi_id; ! 4788: ep->max_host_qng = adv_dvc_varp->max_host_qng; ! 4789: ep->max_dvc_qng = adv_dvc_varp->max_dvc_qng; ! 4790: ep->termination = adv_dvc_varp->cfg->termination; ! 4791: ep->disc_enable = adv_dvc_varp->cfg->disc_enable; ! 4792: ep->bios_ctrl = adv_dvc_varp->bios_ctrl; ! 4793: ep->wdtr_able = adv_dvc_varp->wdtr_able; ! 4794: ep->sdtr_able = adv_dvc_varp->sdtr_able; ! 4795: ep->ultra_able = adv_dvc_varp->ultra_able; ! 4796: ep->tagqng_able = adv_dvc_varp->tagqng_able; ! 4797: ep->start_motor = adv_dvc_varp->start_motor; ! 4798: ep->scsi_reset_delay = adv_dvc_varp->scsi_reset_wait; ! 4799: ep->bios_boot_delay = adv_dvc_varp->cfg->bios_boot_wait; ! 4800: ep->serial_number_word1 = adv_dvc_varp->cfg->serial1; ! 4801: ep->serial_number_word2 = adv_dvc_varp->cfg->serial2; ! 4802: ep->serial_number_word3 = adv_dvc_varp->cfg->serial3; ! 4803: ! 4804: /* ! 4805: * Set the adapter's target id bit in the 'init_tidmask' field. ! 4806: */ ! 4807: boardp->init_tidmask |= ! 4808: ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id); ! 4809: ! 4810: /* ! 4811: * Finish initializing the 'Scsi_Host' structure. ! 4812: */ ! 4813: shp->irq = adv_dvc_varp->irq_no; ! 4814: } ! 4815: ! 4816: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 4817: /* ! 4818: * Channels are numbered beginning with 0. For AdvanSys One host ! 4819: * structure supports one channel. Multi-channel boards have a ! 4820: * separate host structure for each channel. ! 4821: */ ! 4822: shp->max_channel = 0; ! 4823: #endif /* version >= v1.3.89 */ ! 4824: if (ASC_NARROW_BOARD(boardp)) { ! 4825: shp->max_id = ASC_MAX_TID + 1; ! 4826: shp->max_lun = ASC_MAX_LUN + 1; ! 4827: ! 4828: shp->io_port = asc_dvc_varp->iop_base; ! 4829: shp->n_io_port = ASC_IOADR_GAP; ! 4830: shp->this_id = asc_dvc_varp->cfg->chip_scsi_id; ! 4831: ! 4832: /* Set maximum number of queues the adapter can handle. */ ! 4833: shp->can_queue = asc_dvc_varp->max_total_qng; ! 4834: } else { ! 4835: shp->max_id = ADV_MAX_TID + 1; ! 4836: shp->max_lun = ADV_MAX_LUN + 1; ! 4837: ! 4838: /* ! 4839: * Save the I/O Port address and length even though the ! 4840: * in v1.3.0 and greater kernels the region is not used ! 4841: * by a Wide board. Instead the board is accessed with ! 4842: * Memory Mapped I/O. ! 4843: */ ! 4844: shp->io_port = iop; ! 4845: shp->n_io_port = ADV_CONDOR_IOLEN; ! 4846: ! 4847: shp->this_id = adv_dvc_varp->chip_scsi_id; ! 4848: ! 4849: /* Set maximum number of queues the adapter can handle. */ ! 4850: shp->can_queue = adv_dvc_varp->max_host_qng; ! 4851: } ! 4852: ! 4853: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89) ! 4854: /* ! 4855: * In old kernels without tag queuing support and with memory ! 4856: * allocation problems set a conservative 'cmd_per_lun' value. ! 4857: */ ! 4858: #ifdef MODULE ! 4859: shp->cmd_per_lun = 1; ! 4860: #else /* MODULE */ ! 4861: shp->cmd_per_lun = 4; ! 4862: #endif /* MODULE */ ! 4863: ASC_DBG1(1, "advansys_detect: cmd_per_lun: %d\n", shp->cmd_per_lun); ! 4864: #else /* version >= v1.3.89 */ ! 4865: /* ! 4866: * Following v1.3.89, 'cmd_per_lun' is no longer needed ! 4867: * and should be set to zero. ! 4868: * ! 4869: * But because of a bug introduced in v1.3.89 if the driver is ! 4870: * compiled as a module and 'cmd_per_lun' is zero, the Mid-Level ! 4871: * SCSI function 'allocate_device' will panic. To allow the driver ! 4872: * to work as a module in these kernels set 'cmd_per_lun' to 1. ! 4873: */ ! 4874: #ifdef MODULE ! 4875: shp->cmd_per_lun = 1; ! 4876: #else /* MODULE */ ! 4877: shp->cmd_per_lun = 0; ! 4878: #endif /* MODULE */ ! 4879: /* ! 4880: * Use the host 'select_queue_depths' function to determine ! 4881: * the number of commands to queue per device. ! 4882: */ ! 4883: shp->select_queue_depths = advansys_select_queue_depths; ! 4884: #endif /* version >= v1.3.89 */ ! 4885: ! 4886: /* ! 4887: * Set the maximum number of scatter-gather elements the ! 4888: * adapter can handle. ! 4889: */ ! 4890: if (ASC_NARROW_BOARD(boardp)) { ! 4891: /* ! 4892: * Allow two commands with 'sg_tablesize' scatter-gather ! 4893: * elements to be executed simultaneously. This value is ! 4894: * the theoretical hardware limit. It may be decreased ! 4895: * below. ! 4896: */ ! 4897: shp->sg_tablesize = ! 4898: (((asc_dvc_varp->max_total_qng - 2) / 2) * ! 4899: ASC_SG_LIST_PER_Q) + 1; ! 4900: } else { ! 4901: shp->sg_tablesize = ADV_MAX_SG_LIST; ! 4902: } ! 4903: ! 4904: #ifdef MODULE ! 4905: /* ! 4906: * If the driver is compiled as a module, set a limit on the ! 4907: * 'sg_tablesize' value to prevent memory allocation failures. ! 4908: * Memory allocation errors are more likely to occur at module ! 4909: * load time, then at driver initialization time. ! 4910: */ ! 4911: if (shp->sg_tablesize > 64) { ! 4912: shp->sg_tablesize = 64; ! 4913: } ! 4914: #endif /* MODULE */ ! 4915: ! 4916: /* ! 4917: * The value of 'sg_tablesize' can not exceed the SCSI ! 4918: * mid-level driver definition of SG_ALL. SG_ALL also ! 4919: * must not be exceeded, because it is used to define the ! 4920: * size of the scatter-gather table in 'struct asc_sg_head'. ! 4921: */ ! 4922: if (shp->sg_tablesize > SG_ALL) { ! 4923: shp->sg_tablesize = SG_ALL; ! 4924: } ! 4925: ! 4926: ASC_DBG1(1, "advansys_detect: sg_tablesize: %d\n", ! 4927: shp->sg_tablesize); ! 4928: ! 4929: /* BIOS start address. */ ! 4930: if (ASC_NARROW_BOARD(boardp)) { ! 4931: shp->base = (char *) ((ulong) AscGetChipBiosAddress( ! 4932: asc_dvc_varp->iop_base, ! 4933: asc_dvc_varp->bus_type)); ! 4934: } else { ! 4935: /* ! 4936: * Fill-in BIOS board variables. The Wide BIOS saves ! 4937: * information in LRAM that is used by the driver. ! 4938: */ ! 4939: AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_SIGNATURE, ! 4940: boardp->bios_signature); ! 4941: AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_VERSION, ! 4942: boardp->bios_version); ! 4943: AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODESEG, ! 4944: boardp->bios_codeseg); ! 4945: AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODELEN, ! 4946: boardp->bios_codelen); ! 4947: ! 4948: ASC_DBG2(1, ! 4949: "advansys_detect: bios_signature %x, bios_version %x\n", ! 4950: boardp->bios_signature, boardp->bios_version); ! 4951: ! 4952: ASC_DBG2(1, ! 4953: "advansys_detect: bios_codeseg %x, bios_codelen %x\n", ! 4954: boardp->bios_codeseg, boardp->bios_codelen); ! 4955: ! 4956: /* ! 4957: * If the BIOS saved a valid signature, then fill in ! 4958: * the BIOS code segment base address. ! 4959: */ ! 4960: if (boardp->bios_signature == 0x55AA) { ! 4961: /* ! 4962: * Convert x86 realmode code segment to a linear ! 4963: * address by shifting left 4. ! 4964: */ ! 4965: shp->base = (uchar *) (boardp->bios_codeseg << 4); ! 4966: } else { ! 4967: shp->base = 0; ! 4968: } ! 4969: } ! 4970: ! 4971: /* ! 4972: * Register Board Resources - I/O Port, DMA, IRQ ! 4973: */ ! 4974: ! 4975: /* Register I/O port range. */ ! 4976: ASC_DBG(2, "advansys_detect: request_region()\n"); ! 4977: request_region(shp->io_port, shp->n_io_port, "advansys"); ! 4978: ! 4979: /* Register DMA Channel for Narrow boards. */ ! 4980: shp->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */ ! 4981: if (ASC_NARROW_BOARD(boardp)) { ! 4982: /* Register DMA channel for ISA bus. */ ! 4983: if (asc_dvc_varp->bus_type & ASC_IS_ISA) { ! 4984: shp->dma_channel = asc_dvc_varp->cfg->isa_dma_channel; ! 4985: if ((ret = ! 4986: request_dma(shp->dma_channel, "advansys")) != 0) { ! 4987: ASC_PRINT3( ! 4988: "advansys_detect: board %d: request_dma() %d failed %d\n", ! 4989: boardp->id, shp->dma_channel, ret); ! 4990: release_region(shp->io_port, shp->n_io_port); ! 4991: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 4992: kfree(boardp->prtbuf); ! 4993: #endif /* version >= v1.3.0 */ ! 4994: scsi_unregister(shp); ! 4995: asc_board_count--; ! 4996: continue; ! 4997: } ! 4998: AscEnableIsaDma(shp->dma_channel); ! 4999: } ! 5000: } ! 5001: ! 5002: /* Register IRQ Number. */ ! 5003: ASC_DBG1(2, "advansys_detect: request_irq() %d\n", shp->irq); ! 5004: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70) ! 5005: if ((ret = request_irq(shp->irq, advansys_interrupt, ! 5006: SA_INTERRUPT, "advansys")) != 0) ! 5007: #else /* version >= v1.3.70 */ ! 5008: /* ! 5009: * If request_irq() fails with the SA_INTERRUPT flag set, ! 5010: * then try again without the SA_INTERRUPT flag set. This ! 5011: * allows IRQ sharing to work even with other drivers that ! 5012: * do not set the SA_INTERRUPT flag. ! 5013: * ! 5014: * If SA_INTERRUPT is not set, then interrupts are enabled ! 5015: * before the driver interrupt function is called. ! 5016: */ ! 5017: if (((ret = request_irq(shp->irq, advansys_interrupt, ! 5018: SA_INTERRUPT | (share_irq == TRUE ? SA_SHIRQ : 0), ! 5019: "advansys", boardp)) != 0) && ! 5020: ((ret = request_irq(shp->irq, advansys_interrupt, ! 5021: (share_irq == TRUE ? SA_SHIRQ : 0), ! 5022: "advansys", boardp)) != 0)) ! 5023: #endif /* version >= v1.3.70 */ ! 5024: { ! 5025: if (ret == -EBUSY) { ! 5026: ASC_PRINT2( ! 5027: "advansys_detect: board %d: request_irq(): IRQ %d already in use.\n", ! 5028: boardp->id, shp->irq); ! 5029: } else if (ret == -EINVAL) { ! 5030: ASC_PRINT2( ! 5031: "advansys_detect: board %d: request_irq(): IRQ %d not valid.\n", ! 5032: boardp->id, shp->irq); ! 5033: } else { ! 5034: ASC_PRINT3( ! 5035: "advansys_detect: board %d: request_irq(): IRQ %d failed with %d\n", ! 5036: boardp->id, shp->irq, ret); ! 5037: } ! 5038: release_region(shp->io_port, shp->n_io_port); ! 5039: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 5040: iounmap(boardp->ioremap_addr); ! 5041: #endif /* version >= v1,3,0 */ ! 5042: if (shp->dma_channel != NO_ISA_DMA) { ! 5043: free_dma(shp->dma_channel); ! 5044: } ! 5045: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 5046: kfree(boardp->prtbuf); ! 5047: #endif /* version >= v1.3.0 */ ! 5048: scsi_unregister(shp); ! 5049: asc_board_count--; ! 5050: continue; ! 5051: } ! 5052: ! 5053: /* ! 5054: * Initialize board RISC chip and enable interrupts. ! 5055: */ ! 5056: if (ASC_NARROW_BOARD(boardp)) { ! 5057: ASC_DBG(2, "advansys_detect: AscInitAsc1000Driver()\n"); ! 5058: warn_code = AscInitAsc1000Driver(asc_dvc_varp); ! 5059: err_code = asc_dvc_varp->err_code; ! 5060: ! 5061: if (warn_code || err_code) { ! 5062: ASC_PRINT4( ! 5063: "AscInitAsc1000Driver: board %d: error: init_state %x, warn %x error %x\n", ! 5064: boardp->id, asc_dvc_varp->init_state, ! 5065: warn_code, err_code); ! 5066: } ! 5067: } else { ! 5068: int req_cnt; ! 5069: adv_req_t *reqp = NULL; ! 5070: int sg_cnt; ! 5071: adv_sgblk_t *sgp = NULL; ! 5072: ! 5073: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0) ! 5074: req_cnt = sizeof(adv_req_buf)/sizeof(adv_req_t); ! 5075: sg_cnt = sizeof(adv_sgblk_buf)/sizeof(adv_sgblk_t); ! 5076: reqp = (adv_req_t *) &adv_req_buf[0]; ! 5077: sgp = (adv_sgblk_t *) &adv_sgblk_buf[0]; ! 5078: #else /* version >= v1.3.0 */ ! 5079: /* ! 5080: * Allocate up to 'max_host_qng' request structures for ! 5081: * the Wide board. ! 5082: */ ! 5083: for (req_cnt = adv_dvc_varp->max_host_qng; ! 5084: req_cnt > 0; req_cnt--) { ! 5085: ! 5086: reqp = (adv_req_t *) ! 5087: kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC); ! 5088: ! 5089: ASC_DBG3(1, ! 5090: "advansys_detect: reqp %x, req_cnt %d, bytes %d\n", ! 5091: (unsigned) reqp, req_cnt, sizeof(adv_req_t) * req_cnt); ! 5092: ! 5093: if (reqp != NULL) { ! 5094: break; ! 5095: } ! 5096: } ! 5097: ! 5098: /* ! 5099: * Allocate up to ADV_TOT_SG_LIST request structures for ! 5100: * the Wide board. ! 5101: */ ! 5102: for (sg_cnt = ADV_TOT_SG_LIST; sg_cnt > 0; sg_cnt--) { ! 5103: ! 5104: sgp = (adv_sgblk_t *) ! 5105: kmalloc(sizeof(adv_sgblk_t) * sg_cnt, GFP_ATOMIC); ! 5106: ! 5107: ASC_DBG3(1, ! 5108: "advansys_detect: sgp %x, sg_cnt %d, bytes %d\n", ! 5109: (unsigned) sgp, sg_cnt, sizeof(adv_sgblk_t) * sg_cnt); ! 5110: ! 5111: if (sgp != NULL) { ! 5112: break; ! 5113: } ! 5114: } ! 5115: #endif /* version >= v1.3.0 */ ! 5116: ! 5117: /* ! 5118: * If no request structures or scatter-gather structures could ! 5119: * be allocated, then return an error. Otherwise continue with ! 5120: * initialization. ! 5121: */ ! 5122: if (reqp == NULL) { ! 5123: ASC_PRINT1( ! 5124: "advansys_detect: board %d: error: failed to kmalloc() adv_req_t buffer.\n", ! 5125: boardp->id); ! 5126: err_code = ADV_ERROR; ! 5127: } else if (sgp == NULL) { ! 5128: kfree(reqp); ! 5129: ASC_PRINT1( ! 5130: "advansys_detect: board %d: error: failed to kmalloc() adv_sgblk_t buffer.\n", ! 5131: boardp->id); ! 5132: err_code = ADV_ERROR; ! 5133: } else { ! 5134: ! 5135: /* ! 5136: * Save original pointer for kfree() in case the ! 5137: * driver is built as a module and can be unloaded. ! 5138: */ ! 5139: boardp->orig_reqp = reqp; ! 5140: ! 5141: /* ! 5142: * Point 'adv_reqp' to the request structures and ! 5143: * link them together. ! 5144: */ ! 5145: req_cnt--; ! 5146: reqp[req_cnt].next_reqp = NULL; ! 5147: for (; req_cnt > 0; req_cnt--) { ! 5148: reqp[req_cnt - 1].next_reqp = &reqp[req_cnt]; ! 5149: } ! 5150: boardp->adv_reqp = &reqp[0]; ! 5151: ! 5152: /* ! 5153: * Save original pointer for kfree() in case the ! 5154: * driver is built as a module and can be unloaded. ! 5155: */ ! 5156: boardp->orig_sgblkp = sgp; ! 5157: ! 5158: /* ! 5159: * Point 'adv_sgblkp' to the request structures and ! 5160: * link them together. ! 5161: */ ! 5162: sg_cnt--; ! 5163: sgp[sg_cnt].next_sgblkp = NULL; ! 5164: for (; sg_cnt > 0; sg_cnt--) { ! 5165: sgp[sg_cnt - 1].next_sgblkp = &sgp[sg_cnt]; ! 5166: } ! 5167: boardp->adv_sgblkp = &sgp[0]; ! 5168: ! 5169: ASC_DBG(2, "advansys_detect: AdvInitAsc3550Driver()\n"); ! 5170: warn_code = AdvInitAsc3550Driver(adv_dvc_varp); ! 5171: err_code = adv_dvc_varp->err_code; ! 5172: ! 5173: if (warn_code || err_code) { ! 5174: ASC_PRINT3( ! 5175: "AdvInitAsc3550Driver: board %d: error: warn %x, error %x\n", ! 5176: boardp->id, warn_code, adv_dvc_varp->err_code); ! 5177: } ! 5178: } ! 5179: } ! 5180: ! 5181: if (err_code != 0) { ! 5182: release_region(shp->io_port, shp->n_io_port); ! 5183: if (ASC_WIDE_BOARD(boardp)) { ! 5184: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 5185: iounmap(boardp->ioremap_addr); ! 5186: #endif /* version >= v1,3,0 */ ! 5187: if (boardp->orig_reqp) { ! 5188: kfree(boardp->orig_reqp); ! 5189: boardp->orig_reqp = boardp->adv_reqp = NULL; ! 5190: } ! 5191: if (boardp->orig_sgblkp) { ! 5192: kfree(boardp->orig_sgblkp); ! 5193: boardp->orig_sgblkp = boardp->adv_sgblkp = NULL; ! 5194: } ! 5195: } ! 5196: if (shp->dma_channel != NO_ISA_DMA) { ! 5197: free_dma(shp->dma_channel); ! 5198: } ! 5199: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 5200: kfree(boardp->prtbuf); ! 5201: #endif /* version >= v1.3.0 */ ! 5202: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70) ! 5203: free_irq(shp->irq); ! 5204: #else /* version >= v1.3.70 */ ! 5205: free_irq(shp->irq, boardp); ! 5206: #endif /* version >= v1.3.70 */ ! 5207: scsi_unregister(shp); ! 5208: asc_board_count--; ! 5209: continue; ! 5210: } ! 5211: ASC_DBG_PRT_SCSI_HOST(2, shp); ! 5212: } ! 5213: } ! 5214: ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", asc_board_count); ! 5215: return asc_board_count; ! 5216: } ! 5217: ! 5218: /* ! 5219: * advansys_release() ! 5220: * ! 5221: * Release resources allocated for a single AdvanSys adapter. ! 5222: */ ! 5223: int ! 5224: advansys_release(struct Scsi_Host *shp) ! 5225: { ! 5226: asc_board_t *boardp; ! 5227: ! 5228: ASC_DBG(1, "advansys_release: begin\n"); ! 5229: boardp = ASC_BOARDP(shp); ! 5230: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70) ! 5231: free_irq(shp->irq); ! 5232: #else /* version >= v1.3.70 */ ! 5233: free_irq(shp->irq, boardp); ! 5234: #endif /* version >= v1.3.70 */ ! 5235: if (shp->dma_channel != NO_ISA_DMA) { ! 5236: ASC_DBG(1, "advansys_release: free_dma()\n"); ! 5237: free_dma(shp->dma_channel); ! 5238: } ! 5239: release_region(shp->io_port, shp->n_io_port); ! 5240: if (ASC_WIDE_BOARD(boardp)) { ! 5241: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 5242: iounmap(boardp->ioremap_addr); ! 5243: #endif /* version >= v1,3,0 */ ! 5244: if (boardp->orig_reqp) { ! 5245: kfree(boardp->orig_reqp); ! 5246: boardp->orig_reqp = boardp->adv_reqp = NULL; ! 5247: } ! 5248: if (boardp->orig_sgblkp) { ! 5249: kfree(boardp->orig_sgblkp); ! 5250: boardp->orig_sgblkp = boardp->adv_sgblkp = NULL; ! 5251: } ! 5252: } ! 5253: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 5254: ASC_ASSERT(boardp->prtbuf != NULL); ! 5255: kfree(boardp->prtbuf); ! 5256: #endif /* version >= v1.3.0 */ ! 5257: scsi_unregister(shp); ! 5258: ASC_DBG(1, "advansys_release: end\n"); ! 5259: return 0; ! 5260: } ! 5261: ! 5262: /* ! 5263: * advansys_info() ! 5264: * ! 5265: * Return suitable for printing on the console with the argument ! 5266: * adapter's configuration information. ! 5267: * ! 5268: * Note: The information line should not exceed ASC_INFO_SIZE bytes, ! 5269: * otherwise the static 'info' array will be overrun. ! 5270: */ ! 5271: const char * ! 5272: advansys_info(struct Scsi_Host *shp) ! 5273: { ! 5274: static char info[ASC_INFO_SIZE]; ! 5275: asc_board_t *boardp; ! 5276: ASC_DVC_VAR *asc_dvc_varp; ! 5277: ADV_DVC_VAR *adv_dvc_varp; ! 5278: char *busname; ! 5279: ! 5280: boardp = ASC_BOARDP(shp); ! 5281: if (ASC_NARROW_BOARD(boardp)) { ! 5282: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; ! 5283: ASC_DBG(1, "advansys_info: begin\n"); ! 5284: if (asc_dvc_varp->bus_type & ASC_IS_ISA) { ! 5285: if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == ASC_IS_ISAPNP) { ! 5286: busname = "ISA PnP"; ! 5287: } else { ! 5288: busname = "ISA"; ! 5289: } ! 5290: sprintf(info, ! 5291: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92) ! 5292: "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u, DMA %u", ! 5293: #else /* version >= v2.1.92 */ ! 5294: "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %lX/%X, IRQ %u, DMA %u", ! 5295: #endif /* version >= v2.1.92 */ ! 5296: ASC_VERSION, busname, asc_dvc_varp->max_total_qng, ! 5297: (unsigned) shp->base, ! 5298: shp->io_port, shp->n_io_port - 1, ! 5299: shp->irq, shp->dma_channel); ! 5300: } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) { ! 5301: if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA) ! 5302: == ASC_IS_PCI_ULTRA) { ! 5303: busname = "PCI Ultra"; ! 5304: } else { ! 5305: busname = "PCI"; ! 5306: } ! 5307: sprintf(info, ! 5308: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92) ! 5309: "AdvanSys SCSI %s: %s %u CDB: IO %X/%X, IRQ %u", ! 5310: #else /* version >= v2.1.92 */ ! 5311: "AdvanSys SCSI %s: %s %u CDB: IO %lX/%X, IRQ %u", ! 5312: #endif /* version >= v2.1.92 */ ! 5313: ASC_VERSION, busname, asc_dvc_varp->max_total_qng, ! 5314: shp->io_port, shp->n_io_port - 1, shp->irq); ! 5315: } else { ! 5316: if (asc_dvc_varp->bus_type & ASC_IS_VL) { ! 5317: busname = "VL"; ! 5318: } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) { ! 5319: busname = "EISA"; ! 5320: } else { ! 5321: busname = "?"; ! 5322: ASC_PRINT2( ! 5323: "advansys_info: board %d: unknown bus type %d\n", ! 5324: boardp->id, asc_dvc_varp->bus_type); ! 5325: } ! 5326: sprintf(info, ! 5327: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,92) ! 5328: "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X/%X, IRQ %u", ! 5329: #else /* version >= v2.1.92 */ ! 5330: "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %lX/%X, IRQ %u", ! 5331: #endif /* version >= v2.1.92 */ ! 5332: ASC_VERSION, busname, asc_dvc_varp->max_total_qng, ! 5333: (unsigned) shp->base, shp->io_port - 1, ! 5334: shp->n_io_port, shp->irq); ! 5335: } ! 5336: } else { ! 5337: /* ! 5338: * Wide Adapter Information ! 5339: * ! 5340: * Memory-mapped I/O is used instead of I/O space to access ! 5341: * the adapter, but display the I/O Port range. The Memory ! 5342: * I/O address is displayed through the driver /proc file. ! 5343: */ ! 5344: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; ! 5345: if (boardp->bios_signature == 0x55AA) { ! 5346: sprintf(info, ! 5347: "AdvanSys SCSI %s: PCI Ultra-Wide: BIOS %X/%X, IO %X/%X, IRQ %u", ! 5348: ASC_VERSION, ! 5349: boardp->bios_codeseg << 4, ! 5350: boardp->bios_codelen > 0 ? ! 5351: (boardp->bios_codelen << 9) - 1 : 0, ! 5352: (unsigned) boardp->ioport, ADV_CONDOR_IOLEN - 1, ! 5353: shp->irq); ! 5354: } else { ! 5355: sprintf(info, ! 5356: "AdvanSys SCSI %s: PCI Ultra-Wide: IO %X/%X, IRQ %u", ! 5357: ASC_VERSION, ! 5358: (unsigned) boardp->ioport, ! 5359: (ADV_CONDOR_IOLEN - 1), ! 5360: shp->irq); ! 5361: } ! 5362: } ! 5363: ASC_ASSERT(strlen(info) < ASC_INFO_SIZE); ! 5364: ASC_DBG(1, "advansys_info: end\n"); ! 5365: return info; ! 5366: } ! 5367: ! 5368: /* ! 5369: * advansys_command() - polled I/O entrypoint. ! 5370: * ! 5371: * Apparently host drivers shouldn't return until the command ! 5372: * is finished. ! 5373: * ! 5374: * Note: This is an old interface that is no longer used by the SCSI ! 5375: * mid-level driver. The new interface, advansys_queuecommand(), ! 5376: * currently handles all requests. ! 5377: */ ! 5378: int ! 5379: advansys_command(Scsi_Cmnd *scp) ! 5380: { ! 5381: ASC_DBG1(1, "advansys_command: scp %x\n", (unsigned) scp); ! 5382: ASC_STATS(scp->host, command); ! 5383: scp->SCp.Status = 0; /* Set to a known state */ ! 5384: advansys_queuecommand(scp, advansys_command_done); ! 5385: while (scp->SCp.Status == 0) { ! 5386: continue; ! 5387: } ! 5388: ASC_DBG1(1, "advansys_command: result %x\n", scp->result); ! 5389: return scp->result; ! 5390: } ! 5391: ! 5392: /* ! 5393: * advansys_queuecommand() - interrupt-driven I/O entrypoint. ! 5394: * ! 5395: * This function always returns 0. Command return status is saved ! 5396: * in the 'scp' result field. ! 5397: */ ! 5398: int ! 5399: advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *)) ! 5400: { ! 5401: struct Scsi_Host *shp; ! 5402: asc_board_t *boardp; ! 5403: int flags; ! 5404: Scsi_Cmnd *done_scp; ! 5405: ! 5406: shp = scp->host; ! 5407: boardp = ASC_BOARDP(shp); ! 5408: ASC_STATS(shp, queuecommand); ! 5409: ! 5410: /* ! 5411: * Disable interrupts to preserve request ordering and provide ! 5412: * mutually exclusive access to global structures used to initiate ! 5413: * a request. ! 5414: */ ! 5415: save_flags(flags); ! 5416: cli(); ! 5417: ! 5418: /* ! 5419: * Block new commands while handling a reset or abort request. ! 5420: */ ! 5421: if (boardp->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) { ! 5422: if (boardp->flags & ASC_HOST_IN_RESET) { ! 5423: ASC_DBG1(1, ! 5424: "advansys_queuecommand: scp %x blocked for reset request\n", ! 5425: (unsigned) scp); ! 5426: scp->result = HOST_BYTE(DID_RESET); ! 5427: } else { ! 5428: ASC_DBG1(1, ! 5429: "advansys_queuecommand: scp %x blocked for abort request\n", ! 5430: (unsigned) scp); ! 5431: scp->result = HOST_BYTE(DID_ABORT); ! 5432: } ! 5433: ! 5434: /* ! 5435: * Add blocked requests to the board's 'done' queue. The queued ! 5436: * requests will be completed at the end of the abort or reset ! 5437: * handling. ! 5438: */ ! 5439: asc_enqueue(&boardp->done, scp, ASC_BACK); ! 5440: restore_flags(flags); ! 5441: return 0; ! 5442: } ! 5443: ! 5444: /* ! 5445: * Attempt to execute any waiting commands for the board. ! 5446: */ ! 5447: if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { ! 5448: ASC_DBG(1, ! 5449: "advansys_queuecommand: before asc_execute_queue() waiting\n"); ! 5450: asc_execute_queue(&boardp->waiting); ! 5451: } ! 5452: ! 5453: /* ! 5454: * Save the function pointer to Linux mid-level 'done' function ! 5455: * and attempt to execute the command. ! 5456: * ! 5457: * If ASC_ERROR is returned the request has been added to the ! 5458: * board's 'active' queue and will be completed by the interrupt ! 5459: * handler. ! 5460: * ! 5461: * If ASC_BUSY is returned add the request to the board's per ! 5462: * target waiting list. ! 5463: * ! 5464: * If an error occurred, the request will have been placed on the ! 5465: * board's 'done' queue and must be completed before returning. ! 5466: */ ! 5467: scp->scsi_done = done; ! 5468: switch (asc_execute_scsi_cmnd(scp)) { ! 5469: case ASC_NOERROR: ! 5470: break; ! 5471: case ASC_BUSY: ! 5472: asc_enqueue(&boardp->waiting, scp, ASC_BACK); ! 5473: break; ! 5474: case ASC_ERROR: ! 5475: default: ! 5476: done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL); ! 5477: /* Interrupts could be enabled here. */ ! 5478: asc_scsi_done_list(done_scp); ! 5479: break; ! 5480: } ! 5481: ! 5482: restore_flags(flags); ! 5483: return 0; ! 5484: } ! 5485: ! 5486: /* ! 5487: * advansys_abort() ! 5488: * ! 5489: * Abort the command specified by 'scp'. ! 5490: */ ! 5491: int ! 5492: advansys_abort(Scsi_Cmnd *scp) ! 5493: { ! 5494: struct Scsi_Host *shp; ! 5495: asc_board_t *boardp; ! 5496: ASC_DVC_VAR *asc_dvc_varp; ! 5497: ADV_DVC_VAR *adv_dvc_varp; ! 5498: int flags; ! 5499: int do_scsi_done; ! 5500: int scp_found; ! 5501: Scsi_Cmnd *done_scp = NULL; ! 5502: int ret; ! 5503: ! 5504: /* Save current flags and disable interrupts. */ ! 5505: save_flags(flags); ! 5506: cli(); ! 5507: ! 5508: ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp); ! 5509: ! 5510: #ifdef ADVANSYS_STATS ! 5511: if (scp->host != NULL) { ! 5512: ASC_STATS(scp->host, abort); ! 5513: } ! 5514: #endif /* ADVANSYS_STATS */ ! 5515: ! 5516: #ifdef ADVANSYS_ASSERT ! 5517: do_scsi_done = ASC_ERROR; ! 5518: scp_found = ASC_ERROR; ! 5519: ret = ASC_ERROR; ! 5520: #endif /* ADVANSYS_ASSERT */ ! 5521: ! 5522: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 5523: if (scp->serial_number != scp->serial_number_at_timeout) { ! 5524: ASC_PRINT1( ! 5525: "advansys_abort: timeout serial number changed for request %x\n", ! 5526: (unsigned) scp); ! 5527: do_scsi_done = ASC_FALSE; ! 5528: scp_found = ASC_FALSE; ! 5529: ret = SCSI_ABORT_NOT_RUNNING; ! 5530: } else ! 5531: #endif /* version >= v1.3.89 */ ! 5532: if ((shp = scp->host) == NULL) { ! 5533: scp->result = HOST_BYTE(DID_ERROR); ! 5534: do_scsi_done = ASC_TRUE; ! 5535: scp_found = ASC_FALSE; ! 5536: ret = SCSI_ABORT_ERROR; ! 5537: } else if ((boardp = ASC_BOARDP(shp))->flags & ! 5538: (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) { ! 5539: ASC_PRINT2( ! 5540: "advansys_abort: board %d: Nested host reset or abort, flags 0x%x\n", ! 5541: boardp->id, boardp->flags); ! 5542: do_scsi_done = ASC_TRUE; ! 5543: if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) || ! 5544: (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) { ! 5545: scp_found = ASC_TRUE; ! 5546: } else { ! 5547: scp_found = ASC_FALSE; ! 5548: } ! 5549: scp->result = HOST_BYTE(DID_ERROR); ! 5550: ret = SCSI_ABORT_ERROR; ! 5551: } else { ! 5552: /* Set abort flag to avoid nested reset or abort requests. */ ! 5553: boardp->flags |= ASC_HOST_IN_ABORT; ! 5554: ! 5555: do_scsi_done = ASC_TRUE; ! 5556: if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) { ! 5557: /* ! 5558: * If asc_rmqueue() found the command on the waiting ! 5559: * queue, it had not been sent to the device. After ! 5560: * the queue is removed, no other handling is required. ! 5561: */ ! 5562: ASC_DBG1(1, "advansys_abort: scp %x found on waiting queue\n", ! 5563: (unsigned) scp); ! 5564: scp_found = ASC_TRUE; ! 5565: scp->result = HOST_BYTE(DID_ABORT); ! 5566: ret = SCSI_ABORT_SUCCESS; ! 5567: } else if (asc_isqueued(&boardp->active, scp) == ASC_TRUE) { ! 5568: /* ! 5569: * If asc_isqueued() found the command on the active ! 5570: * queue, it has been sent to the device. The command ! 5571: * will be returned through the interrupt handler after ! 5572: * it has been aborted. ! 5573: */ ! 5574: ! 5575: if (ASC_NARROW_BOARD(boardp)) { ! 5576: /* ! 5577: * Narrow Board ! 5578: */ ! 5579: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; ! 5580: scp->result = HOST_BYTE(DID_ABORT); ! 5581: ! 5582: sti(); /* Enable interrupts for AscAbortSRB(). */ ! 5583: ASC_DBG1(1, "advansys_abort: before AscAbortSRB(), scp %x\n", ! 5584: (unsigned) scp); ! 5585: switch (AscAbortSRB(asc_dvc_varp, (ulong) scp)) { ! 5586: case ASC_TRUE: ! 5587: /* asc_isr_callback() will be called */ ! 5588: ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n"); ! 5589: ret = SCSI_ABORT_PENDING; ! 5590: break; ! 5591: case ASC_FALSE: ! 5592: /* Request has apparently already completed. */ ! 5593: ASC_DBG(1, "advansys_abort: AscAbortSRB() FALSE\n"); ! 5594: ret = SCSI_ABORT_NOT_RUNNING; ! 5595: break; ! 5596: case ASC_ERROR: ! 5597: default: ! 5598: ASC_DBG(1, "advansys_abort: AscAbortSRB() ERROR\n"); ! 5599: ret = SCSI_ABORT_ERROR; ! 5600: break; ! 5601: } ! 5602: cli(); ! 5603: } else { ! 5604: /* ! 5605: * Wide Board ! 5606: */ ! 5607: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; ! 5608: scp->result = HOST_BYTE(DID_ABORT); ! 5609: ! 5610: ASC_DBG1(1, "advansys_abort: before AdvAbortSRB(), scp %x\n", ! 5611: (unsigned) scp); ! 5612: switch (AdvAbortSRB(adv_dvc_varp, (ulong) scp)) { ! 5613: case ASC_TRUE: ! 5614: /* asc_isr_callback() will be called */ ! 5615: ASC_DBG(1, "advansys_abort: AdvAbortSRB() TRUE\n"); ! 5616: ret = SCSI_ABORT_PENDING; ! 5617: break; ! 5618: case ASC_FALSE: ! 5619: /* Request has apparently already completed. */ ! 5620: ASC_DBG(1, "advansys_abort: AdvAbortSRB() FALSE\n"); ! 5621: ret = SCSI_ABORT_NOT_RUNNING; ! 5622: break; ! 5623: case ASC_ERROR: ! 5624: default: ! 5625: ASC_DBG(1, "advansys_abort: AdvAbortSRB() ERROR\n"); ! 5626: ret = SCSI_ABORT_ERROR; ! 5627: break; ! 5628: } ! 5629: /* ! 5630: * Ensure all requests completed by the microcode have ! 5631: * been processed by calling AdvISR(). ! 5632: */ ! 5633: (void) AdvISR(adv_dvc_varp); ! 5634: } ! 5635: ! 5636: /* ! 5637: * The request will either still be on the active queue ! 5638: * or have been added to the board's done queue. ! 5639: */ ! 5640: if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) { ! 5641: scp->result = HOST_BYTE(DID_ABORT); ! 5642: scp_found = ASC_TRUE; ! 5643: } else { ! 5644: scp_found = asc_rmqueue(&boardp->done, scp); ! 5645: ASC_ASSERT(scp_found == ASC_TRUE); ! 5646: } ! 5647: ! 5648: } else { ! 5649: /* ! 5650: * The command was not found on the active or waiting queues. ! 5651: */ ! 5652: do_scsi_done = ASC_TRUE; ! 5653: scp_found = ASC_FALSE; ! 5654: ret = SCSI_ABORT_NOT_RUNNING; ! 5655: } ! 5656: ! 5657: /* Clear abort flag. */ ! 5658: boardp->flags &= ~ASC_HOST_IN_ABORT; ! 5659: ! 5660: /* ! 5661: * Because the ASC_HOST_IN_ABORT flag causes both ! 5662: * 'advansys_interrupt' and 'asc_isr_callback' to ! 5663: * queue requests to the board's 'done' queue and ! 5664: * prevents waiting commands from being executed, ! 5665: * these queued requests must be handled here. ! 5666: */ ! 5667: done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL); ! 5668: ! 5669: /* ! 5670: * Start any waiting commands for the board. ! 5671: */ ! 5672: if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { ! 5673: ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n"); ! 5674: asc_execute_queue(&boardp->waiting); ! 5675: } ! 5676: } ! 5677: ! 5678: /* Interrupts could be enabled here. */ ! 5679: ! 5680: /* ! 5681: * Complete the request to be aborted, unless it has been ! 5682: * restarted as detected above, even if it was not found on ! 5683: * the device active or waiting queues. ! 5684: */ ! 5685: ASC_ASSERT(do_scsi_done != ASC_ERROR); ! 5686: ASC_ASSERT(scp_found != ASC_ERROR); ! 5687: if (do_scsi_done == ASC_TRUE) { ! 5688: if (scp->scsi_done == NULL) { ! 5689: ASC_PRINT1( ! 5690: "advansys_abort: aborted request scsi_done() is NULL, %x\n", ! 5691: (unsigned) scp); ! 5692: } else { ! 5693: if (scp_found == ASC_FALSE) { ! 5694: ASC_PRINT1( ! 5695: "advansys_abort: abort request not active or waiting, completing anyway %x\n", ! 5696: (unsigned) scp); ! 5697: } ! 5698: ASC_STATS(scp->host, done); ! 5699: scp->scsi_done(scp); ! 5700: } ! 5701: } ! 5702: ! 5703: /* ! 5704: * It is possible for the request done function to re-enable ! 5705: * interrupts without confusing the driver. But here interrupts ! 5706: * aren't enabled until all requests have been completed. ! 5707: */ ! 5708: if (done_scp != NULL) { ! 5709: asc_scsi_done_list(done_scp); ! 5710: } ! 5711: ! 5712: ASC_DBG1(1, "advansys_abort: ret %d\n", ret); ! 5713: ! 5714: /* Re-enable interrupts, if they were enabled on entry. */ ! 5715: restore_flags(flags); ! 5716: ! 5717: ASC_ASSERT(ret != ASC_ERROR); ! 5718: return ret; ! 5719: } ! 5720: ! 5721: /* ! 5722: * advansys_reset() ! 5723: * ! 5724: * Reset the device associated with the command 'scp'. ! 5725: */ ! 5726: int ! 5727: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89) ! 5728: advansys_reset(Scsi_Cmnd *scp) ! 5729: #else /* version >= v1.3.89 */ ! 5730: advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags) ! 5731: #endif /* version >= v1.3.89 */ ! 5732: { ! 5733: struct Scsi_Host *shp; ! 5734: asc_board_t *boardp; ! 5735: ASC_DVC_VAR *asc_dvc_varp; ! 5736: ADV_DVC_VAR *adv_dvc_varp; ! 5737: int flags; ! 5738: Scsi_Cmnd *done_scp = NULL, *last_scp = NULL; ! 5739: Scsi_Cmnd *tscp, *new_last_scp; ! 5740: int do_scsi_done; ! 5741: int scp_found; ! 5742: int status; ! 5743: int target; ! 5744: int ret; ! 5745: int device_reset = ASC_FALSE; ! 5746: ! 5747: /* Save current flags and disable interrupts. */ ! 5748: save_flags(flags); ! 5749: cli(); ! 5750: ! 5751: ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp); ! 5752: ! 5753: #ifdef ADVANSYS_STATS ! 5754: if (scp->host != NULL) { ! 5755: ASC_STATS(scp->host, reset); ! 5756: } ! 5757: #endif /* ADVANSYS_STATS */ ! 5758: ! 5759: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 5760: if ((reset_flags & SCSI_RESET_ASYNCHRONOUS) && ! 5761: (scp->serial_number != scp->serial_number_at_timeout)) { ! 5762: ASC_PRINT1( ! 5763: "advansys_reset: timeout serial number changed for request %x\n", ! 5764: (unsigned) scp); ! 5765: do_scsi_done = ASC_FALSE; ! 5766: scp_found = ASC_FALSE; ! 5767: ret = SCSI_RESET_NOT_RUNNING; ! 5768: } else ! 5769: #endif /* version >= v1.3.89 */ ! 5770: if ((shp = scp->host) == NULL) { ! 5771: scp->result = HOST_BYTE(DID_ERROR); ! 5772: do_scsi_done = ASC_TRUE; ! 5773: scp_found = ASC_FALSE; ! 5774: ret = SCSI_RESET_ERROR; ! 5775: } else if ((boardp = ASC_BOARDP(shp))->flags & ! 5776: (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) { ! 5777: ASC_PRINT2( ! 5778: "advansys_reset: board %d: Nested host reset or abort, flags 0x%x\n", ! 5779: boardp->id, boardp->flags); ! 5780: do_scsi_done = ASC_TRUE; ! 5781: if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) || ! 5782: (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) { ! 5783: scp_found = ASC_TRUE; ! 5784: } else { ! 5785: scp_found = ASC_FALSE; ! 5786: } ! 5787: scp->result = HOST_BYTE(DID_ERROR); ! 5788: ret = SCSI_RESET_ERROR; ! 5789: } else if (jiffies >= boardp->last_reset && ! 5790: jiffies < (boardp->last_reset + (10 * HZ))) { ! 5791: /* ! 5792: * Don't allow a reset to be attempted within 10 seconds ! 5793: * of the last reset. ! 5794: * ! 5795: * If 'jiffies' wrapping occurs, the reset request will go ! 5796: * through, because a wrapped 'jiffies' would not pass the ! 5797: * test above. ! 5798: */ ! 5799: ASC_DBG(1, ! 5800: "advansys_reset: reset within 10 sec of last reset ignored\n"); ! 5801: do_scsi_done = ASC_TRUE; ! 5802: if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) || ! 5803: (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) { ! 5804: scp_found = ASC_TRUE; ! 5805: } else { ! 5806: scp_found = ASC_FALSE; ! 5807: } ! 5808: scp->result = HOST_BYTE(DID_ERROR); ! 5809: ret = SCSI_RESET_ERROR; ! 5810: } else { ! 5811: do_scsi_done = ASC_TRUE; ! 5812: ! 5813: /* Set reset flag to avoid nested reset or abort requests. */ ! 5814: boardp->flags |= ASC_HOST_IN_RESET; ! 5815: ! 5816: /* ! 5817: * If the request is on the target waiting or active queue ! 5818: * or the board done queue, then remove it and note that it ! 5819: * was found. ! 5820: */ ! 5821: if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) { ! 5822: ASC_DBG(1, "advansys_reset: active scp_found = TRUE\n"); ! 5823: scp_found = ASC_TRUE; ! 5824: } else if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) { ! 5825: ASC_DBG(1, "advansys_reset: waiting scp_found = TRUE\n"); ! 5826: scp_found = ASC_TRUE; ! 5827: } else if (asc_rmqueue(&boardp->done, scp) == ASC_TRUE) { ! 5828: scp_found = ASC_TRUE; ! 5829: } else { ! 5830: scp_found = ASC_FALSE; ! 5831: } ! 5832: ! 5833: ! 5834: if (ASC_NARROW_BOARD(boardp)) { ! 5835: /* ! 5836: * Narrow Board ! 5837: * ! 5838: * If the suggest reset bus flags are set, then reset the bus. ! 5839: * Otherwise only reset the device. ! 5840: */ ! 5841: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; ! 5842: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 5843: if (reset_flags & ! 5844: (SCSI_RESET_SUGGEST_BUS_RESET | ! 5845: SCSI_RESET_SUGGEST_HOST_RESET)) { ! 5846: #endif /* version >= v1.3.89 */ ! 5847: ! 5848: /* ! 5849: * Reset the target's SCSI bus. ! 5850: */ ! 5851: ASC_DBG(1, "advansys_reset: before AscResetSB()\n"); ! 5852: sti(); /* Enable interrupts for AscResetSB(). */ ! 5853: status = AscResetSB(asc_dvc_varp); ! 5854: cli(); ! 5855: switch (status) { ! 5856: case ASC_TRUE: ! 5857: ASC_DBG(1, "advansys_reset: AscResetSB() success\n"); ! 5858: ret = SCSI_RESET_SUCCESS; ! 5859: break; ! 5860: case ASC_ERROR: ! 5861: default: ! 5862: ASC_DBG(1, "advansys_reset: AscResetSB() failed\n"); ! 5863: ret = SCSI_RESET_ERROR; ! 5864: break; ! 5865: } ! 5866: ! 5867: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 5868: } else { ! 5869: /* ! 5870: * Reset the specified device. If the device reset fails, ! 5871: * then reset the SCSI bus. ! 5872: */ ! 5873: ! 5874: ASC_DBG1(1, ! 5875: "advansys_reset: before AscResetDevice(), target %d\n", ! 5876: scp->target); ! 5877: sti(); /* Enable interrupts for AscResetDevice(). */ ! 5878: status = AscResetDevice(asc_dvc_varp, scp->target); ! 5879: cli(); ! 5880: ! 5881: switch (status) { ! 5882: case ASC_TRUE: ! 5883: ASC_DBG(1, "advansys_reset: AscResetDevice() success\n"); ! 5884: device_reset = ASC_TRUE; ! 5885: ret = SCSI_RESET_SUCCESS; ! 5886: break; ! 5887: case ASC_ERROR: ! 5888: default: ! 5889: ASC_DBG(1, ! 5890: "advansys_reset: AscResetDevice() failed; Calling AscResetSB()\n"); ! 5891: sti(); /* Enable interrupts for AscResetSB(). */ ! 5892: status = AscResetSB(asc_dvc_varp); ! 5893: cli(); ! 5894: switch (status) { ! 5895: case ASC_TRUE: ! 5896: ASC_DBG(1, "advansys_reset: AscResetSB() TRUE\n"); ! 5897: ret = SCSI_RESET_SUCCESS; ! 5898: break; ! 5899: case ASC_ERROR: ! 5900: default: ! 5901: ASC_DBG(1, "advansys_reset: AscResetSB() ERROR\n"); ! 5902: ret = SCSI_RESET_ERROR; ! 5903: break; ! 5904: } ! 5905: break; ! 5906: } ! 5907: } ! 5908: #endif /* version >= v1.3.89 */ ! 5909: } else { ! 5910: /* ! 5911: * Wide Board ! 5912: * ! 5913: * If the suggest reset bus flags are set, then reset the bus. ! 5914: * Otherwise only reset the device. ! 5915: */ ! 5916: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; ! 5917: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 5918: if (reset_flags & ! 5919: (SCSI_RESET_SUGGEST_BUS_RESET | ! 5920: SCSI_RESET_SUGGEST_HOST_RESET)) { ! 5921: #endif /* version >= v1.3.89 */ ! 5922: ! 5923: /* ! 5924: * Reset the target's SCSI bus. ! 5925: */ ! 5926: ASC_DBG(1, "advansys_reset: before AdvResetSB()\n"); ! 5927: switch (AdvResetSB(adv_dvc_varp)) { ! 5928: case ASC_TRUE: ! 5929: ASC_DBG(1, "advansys_reset: AdvResetSB() success\n"); ! 5930: ret = SCSI_RESET_SUCCESS; ! 5931: break; ! 5932: case ASC_FALSE: ! 5933: default: ! 5934: ASC_DBG(1, "advansys_reset: AdvResetSB() failed\n"); ! 5935: ret = SCSI_RESET_ERROR; ! 5936: break; ! 5937: } ! 5938: /* ! 5939: * Ensure all requests completed by the microcode have ! 5940: * been processed by calling AdvISR(). ! 5941: */ ! 5942: (void) AdvISR(adv_dvc_varp); ! 5943: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 5944: } else { ! 5945: /* ! 5946: * Reset the specified device. If the device reset fails, ! 5947: * then reset the SCSI bus. ! 5948: */ ! 5949: ! 5950: ASC_DBG1(1, ! 5951: "advansys_reset: before AdvResetDevice(), target %d\n", ! 5952: scp->target); ! 5953: ! 5954: switch (AdvResetDevice(adv_dvc_varp, scp->target)) { ! 5955: case ASC_TRUE: ! 5956: ASC_DBG(1, "advansys_reset: AdvResetDevice() success\n"); ! 5957: device_reset = ASC_TRUE; ! 5958: ret = SCSI_RESET_SUCCESS; ! 5959: break; ! 5960: case ASC_FALSE: ! 5961: default: ! 5962: ASC_DBG(1, ! 5963: "advansys_reset: AdvResetDevice() failed; Calling AdvResetSB()\n"); ! 5964: ! 5965: switch (AdvResetSB(adv_dvc_varp)) { ! 5966: case ASC_TRUE: ! 5967: ASC_DBG(1, "advansys_reset: AdvResetSB() TRUE\n"); ! 5968: ret = SCSI_RESET_SUCCESS; ! 5969: break; ! 5970: case ASC_FALSE: ! 5971: default: ! 5972: ASC_DBG(1, "advansys_reset: AdvResetSB() ERROR\n"); ! 5973: ret = SCSI_RESET_ERROR; ! 5974: break; ! 5975: } ! 5976: break; ! 5977: } ! 5978: /* ! 5979: * Ensure all requests completed by the microcode have ! 5980: * been processed by calling AdvISR(). ! 5981: */ ! 5982: (void) AdvISR(adv_dvc_varp); ! 5983: } ! 5984: #endif /* version >= v1.3.89 */ ! 5985: } ! 5986: ! 5987: /* ! 5988: * Because the ASC_HOST_IN_RESET flag causes both ! 5989: * 'advansys_interrupt' and 'asc_isr_callback' to ! 5990: * queue requests to the board's 'done' queue and ! 5991: * prevents waiting commands from being executed, ! 5992: * these queued requests must be handled here. ! 5993: */ ! 5994: done_scp = asc_dequeue_list(&boardp->done, &last_scp, ! 5995: ASC_TID_ALL); ! 5996: ! 5997: /* ! 5998: * If a device reset was performed dequeue all waiting ! 5999: * and active requests for the device and set the request ! 6000: * status to DID_RESET. ! 6001: * ! 6002: * If a SCSI bus reset was performed dequeue all waiting ! 6003: * and active requests for all devices and set the request ! 6004: * status to DID_RESET. ! 6005: */ ! 6006: if (device_reset == ASC_TRUE) { ! 6007: target = scp->target; ! 6008: } else { ! 6009: target = ASC_TID_ALL; ! 6010: } ! 6011: ! 6012: /* ! 6013: * Add active requests to 'done_scp' and set the request status ! 6014: * to DID_RESET. ! 6015: */ ! 6016: if (done_scp == NULL) { ! 6017: done_scp = asc_dequeue_list(&boardp->active, &last_scp, target); ! 6018: for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) { ! 6019: tscp->result = HOST_BYTE(DID_RESET); ! 6020: } ! 6021: } else { ! 6022: ASC_ASSERT(last_scp != NULL); ! 6023: REQPNEXT(last_scp) = asc_dequeue_list(&boardp->active, ! 6024: &new_last_scp, target); ! 6025: if (new_last_scp != NULL) { ! 6026: ASC_ASSERT(REQPNEXT(last_scp) != NULL); ! 6027: for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) { ! 6028: tscp->result = HOST_BYTE(DID_RESET); ! 6029: } ! 6030: last_scp = new_last_scp; ! 6031: } ! 6032: } ! 6033: ! 6034: /* ! 6035: * Add waiting requests to 'done_scp' and set the request status ! 6036: * to DID_RESET. ! 6037: */ ! 6038: if (done_scp == NULL) { ! 6039: done_scp = asc_dequeue_list(&boardp->waiting, &last_scp, target); ! 6040: for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) { ! 6041: tscp->result = HOST_BYTE(DID_RESET); ! 6042: } ! 6043: } else { ! 6044: ASC_ASSERT(last_scp != NULL); ! 6045: REQPNEXT(last_scp) = asc_dequeue_list(&boardp->waiting, ! 6046: &new_last_scp, target); ! 6047: if (new_last_scp != NULL) { ! 6048: ASC_ASSERT(REQPNEXT(last_scp) != NULL); ! 6049: for (tscp = REQPNEXT(last_scp); tscp; tscp = REQPNEXT(tscp)) { ! 6050: tscp->result = HOST_BYTE(DID_RESET); ! 6051: } ! 6052: last_scp = new_last_scp; ! 6053: } ! 6054: } ! 6055: ! 6056: /* Save the time of the most recently completed reset. */ ! 6057: boardp->last_reset = jiffies; ! 6058: ! 6059: /* Clear reset flag. */ ! 6060: boardp->flags &= ~ASC_HOST_IN_RESET; ! 6061: ! 6062: /* ! 6063: * Start any waiting commands for the board. ! 6064: */ ! 6065: if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { ! 6066: ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n"); ! 6067: asc_execute_queue(&boardp->waiting); ! 6068: } ! 6069: ret = SCSI_RESET_SUCCESS; ! 6070: } ! 6071: ! 6072: /* Interrupts could be enabled here. */ ! 6073: ! 6074: ASC_ASSERT(do_scsi_done != ASC_ERROR); ! 6075: ASC_ASSERT(scp_found != ASC_ERROR); ! 6076: if (do_scsi_done == ASC_TRUE) { ! 6077: if (scp->scsi_done == NULL) { ! 6078: ASC_PRINT1( ! 6079: "advansys_reset: reset request scsi_done() is NULL, %x\n", ! 6080: (unsigned) scp); ! 6081: } else { ! 6082: if (scp_found == ASC_FALSE) { ! 6083: ASC_PRINT1( ! 6084: "advansys_reset: reset request not active or waiting, completing anyway %x\n", ! 6085: (unsigned) scp); ! 6086: } ! 6087: ASC_STATS(scp->host, done); ! 6088: scp->scsi_done(scp); ! 6089: } ! 6090: } ! 6091: ! 6092: /* ! 6093: * It is possible for the request done function to re-enable ! 6094: * interrupts without confusing the driver. But here interrupts ! 6095: * aren't enabled until requests have been completed. ! 6096: */ ! 6097: if (done_scp != NULL) { ! 6098: asc_scsi_done_list(done_scp); ! 6099: } ! 6100: ! 6101: ASC_DBG1(1, "advansys_reset: ret %d\n", ret); ! 6102: ! 6103: /* Re-enable interrupts, if they were enabled on entry. */ ! 6104: restore_flags(flags); ! 6105: ! 6106: ASC_ASSERT(ret != ASC_ERROR); ! 6107: return ret; ! 6108: } ! 6109: ! 6110: /* ! 6111: * advansys_biosparam() ! 6112: * ! 6113: * Translate disk drive geometry if the "BIOS greater than 1 GB" ! 6114: * support is enabled for a drive. ! 6115: * ! 6116: * ip (information pointer) is an int array with the following definition: ! 6117: * ip[0]: heads ! 6118: * ip[1]: sectors ! 6119: * ip[2]: cylinders ! 6120: */ ! 6121: int ! 6122: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0) ! 6123: advansys_biosparam(Disk *dp, int dep, int ip[]) ! 6124: #else /* version >= v1.3.0 */ ! 6125: advansys_biosparam(Disk *dp, kdev_t dep, int ip[]) ! 6126: #endif /* version >= v1.3.0 */ ! 6127: { ! 6128: asc_board_t *boardp; ! 6129: ! 6130: ASC_DBG(1, "advansys_biosparam: begin\n"); ! 6131: ASC_STATS(dp->device->host, biosparam); ! 6132: boardp = ASC_BOARDP(dp->device->host); ! 6133: if (ASC_NARROW_BOARD(boardp)) { ! 6134: if ((boardp->dvc_var.asc_dvc_var.dvc_cntl & ! 6135: ASC_CNTL_BIOS_GT_1GB) && dp->capacity > 0x200000) { ! 6136: ip[0] = 255; ! 6137: ip[1] = 63; ! 6138: } else { ! 6139: ip[0] = 64; ! 6140: ip[1] = 32; ! 6141: } ! 6142: } else { ! 6143: if ((boardp->dvc_var.adv_dvc_var.bios_ctrl & ! 6144: BIOS_CTRL_EXTENDED_XLAT) && dp->capacity > 0x200000) { ! 6145: ip[0] = 255; ! 6146: ip[1] = 63; ! 6147: } else { ! 6148: ip[0] = 64; ! 6149: ip[1] = 32; ! 6150: } ! 6151: } ! 6152: ip[2] = dp->capacity / (ip[0] * ip[1]); ! 6153: ASC_DBG(1, "advansys_biosparam: end\n"); ! 6154: return 0; ! 6155: } ! 6156: ! 6157: /* ! 6158: * advansys_setup() ! 6159: * ! 6160: * This function is called from init/main.c at boot time. ! 6161: * It it passed LILO parameters that can be set from the ! 6162: * LILO command line or in /etc/lilo.conf. ! 6163: * ! 6164: * It is used by the AdvanSys driver to either disable I/O ! 6165: * port scanning or to limit scanning to 1 - 4 I/O ports. ! 6166: * Regardless of the option setting EISA and PCI boards ! 6167: * will still be searched for and detected. This option ! 6168: * only affects searching for ISA and VL boards. ! 6169: * ! 6170: * If ADVANSYS_DEBUG is defined the driver debug level may ! 6171: * be set using the 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port. ! 6172: * ! 6173: * Examples: ! 6174: * 1. Eliminate I/O port scanning: ! 6175: * boot: linux advansys= ! 6176: * or ! 6177: * boot: linux advansys=0x0 ! 6178: * 2. Limit I/O port scanning to one I/O port: ! 6179: * boot: linux advansys=0x110 ! 6180: * 3. Limit I/O port scanning to four I/O ports: ! 6181: * boot: linux advansys=0x110,0x210,0x230,0x330 ! 6182: * 4. If ADVANSYS_DEBUG, limit I/O port scanning to four I/O ports and ! 6183: * set the driver debug level to 2. ! 6184: * boot: linux advansys=0x110,0x210,0x230,0x330,0xdeb2 ! 6185: * ! 6186: * ints[0] - number of arguments ! 6187: * ints[1] - first argument ! 6188: * ints[2] - second argument ! 6189: * ... ! 6190: */ ! 6191: ASC_INITFUNC( ! 6192: void ! 6193: advansys_setup(char *str, int *ints) ! 6194: ) ! 6195: { ! 6196: int i; ! 6197: ! 6198: if (asc_iopflag == ASC_TRUE) { ! 6199: printk("AdvanSys SCSI: 'advansys' LILO option may appear only once\n"); ! 6200: return; ! 6201: } ! 6202: ! 6203: asc_iopflag = ASC_TRUE; ! 6204: ! 6205: if (ints[0] > ASC_NUM_IOPORT_PROBE) { ! 6206: #ifdef ADVANSYS_DEBUG ! 6207: if ((ints[0] == ASC_NUM_IOPORT_PROBE + 1) && ! 6208: (ints[ASC_NUM_IOPORT_PROBE + 1] >> 4 == 0xdeb)) { ! 6209: asc_dbglvl = ints[ASC_NUM_IOPORT_PROBE + 1] & 0xf; ! 6210: } else { ! 6211: #endif /* ADVANSYS_DEBUG */ ! 6212: printk("AdvanSys SCSI: only %d I/O ports accepted\n", ! 6213: ASC_NUM_IOPORT_PROBE); ! 6214: #ifdef ADVANSYS_DEBUG ! 6215: } ! 6216: #endif /* ADVANSYS_DEBUG */ ! 6217: } ! 6218: ! 6219: #ifdef ADVANSYS_DEBUG ! 6220: ASC_DBG1(1, "advansys_setup: ints[0] %d\n", ints[0]); ! 6221: for (i = 1; i < ints[0]; i++) { ! 6222: ASC_DBG2(1, " ints[%d] %x", i, ints[i]); ! 6223: } ! 6224: ASC_DBG(1, "\n"); ! 6225: #endif /* ADVANSYS_DEBUG */ ! 6226: ! 6227: for (i = 1; i <= ints[0] && i <= ASC_NUM_IOPORT_PROBE; i++) { ! 6228: asc_ioport[i-1] = ints[i]; ! 6229: ASC_DBG2(1, "advansys_setup: asc_ioport[%d] %x\n", ! 6230: i - 1, asc_ioport[i-1]); ! 6231: } ! 6232: } ! 6233: ! 6234: ! 6235: /* ! 6236: * --- Loadable Driver Support ! 6237: */ ! 6238: ! 6239: #ifdef MODULE ! 6240: Scsi_Host_Template driver_template = ADVANSYS; ! 6241: # include "scsi_module.c" ! 6242: #endif /* MODULE */ ! 6243: ! 6244: ! 6245: /* ! 6246: * --- Miscellaneous Driver Functions ! 6247: */ ! 6248: ! 6249: /* ! 6250: * First-level interrupt handler. ! 6251: * ! 6252: * For versions > v1.3.70, 'dev_id' is a pointer to the interrupting ! 6253: * adapter's asc_board_t. Because all boards are currently checked ! 6254: * for interrupts on each interrupt, 'dev_id' is not referenced. 'dev_id' ! 6255: * could be used to identify an interrupt passed to the AdvanSys driver, ! 6256: * which is for a device sharing an interrupt with an AdvanSys adapter. ! 6257: */ ! 6258: STATIC void ! 6259: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,70) ! 6260: advansys_interrupt(int irq, struct pt_regs *regs) ! 6261: #else /* version >= v1.3.70 */ ! 6262: advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs) ! 6263: #endif /* version >= v1.3.70 */ ! 6264: { ! 6265: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95) ! 6266: int flags; ! 6267: #else /* version >= v2.1.95 */ ! 6268: unsigned long flags; ! 6269: #endif /* version >= v2.1.95 */ ! 6270: int i; ! 6271: asc_board_t *boardp; ! 6272: Scsi_Cmnd *done_scp = NULL, *last_scp = NULL; ! 6273: Scsi_Cmnd *new_last_scp; ! 6274: ! 6275: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95) ! 6276: /* Disable interrupts, if they aren't already disabled. */ ! 6277: save_flags(flags); ! 6278: cli(); ! 6279: #else /* version >= v2.1.95 */ ! 6280: /* ! 6281: * Disable interrupts, if they aren't already disabled and acquire ! 6282: * the I/O spinlock. ! 6283: */ ! 6284: spin_lock_irqsave(&io_request_lock, flags); ! 6285: #endif /* version >= v2.1.95 */ ! 6286: ! 6287: ASC_DBG(1, "advansys_interrupt: begin\n"); ! 6288: ! 6289: /* ! 6290: * Check for interrupts on all boards. ! 6291: * AscISR() will call asc_isr_callback(). ! 6292: */ ! 6293: for (i = 0; i < asc_board_count; i++) { ! 6294: boardp = ASC_BOARDP(asc_host[i]); ! 6295: ASC_DBG2(2, "advansys_interrupt: i %d, boardp %lx\n", ! 6296: i, (ulong) boardp) ! 6297: if (ASC_NARROW_BOARD(boardp)) { ! 6298: /* ! 6299: * Narrow Board ! 6300: */ ! 6301: if (AscIsIntPending(asc_host[i]->io_port)) { ! 6302: ASC_STATS(asc_host[i], interrupt); ! 6303: ASC_DBG(1, "advansys_interrupt: before AscISR()\n"); ! 6304: AscISR(&boardp->dvc_var.asc_dvc_var); ! 6305: } ! 6306: } else { ! 6307: /* ! 6308: * Wide Board ! 6309: */ ! 6310: ASC_DBG(1, "advansys_interrupt: before AdvISR()\n"); ! 6311: if (AdvISR(&boardp->dvc_var.adv_dvc_var)) { ! 6312: ASC_STATS(asc_host[i], interrupt); ! 6313: } ! 6314: } ! 6315: ! 6316: /* ! 6317: * Start waiting requests and create a list of completed requests. ! 6318: * ! 6319: * If a reset or abort request is being performed for the board, ! 6320: * the reset or abort handler will complete pending requests after ! 6321: * it has completed. ! 6322: */ ! 6323: if ((boardp->flags & (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) == 0) { ! 6324: ASC_DBG2(1, "advansys_interrupt: done_scp %lx, last_scp %lx\n", ! 6325: (ulong) done_scp, (ulong) last_scp); ! 6326: ! 6327: /* Start any waiting commands for the board. */ ! 6328: if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { ! 6329: ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n"); ! 6330: asc_execute_queue(&boardp->waiting); ! 6331: } ! 6332: ! 6333: /* ! 6334: * Add to the list of requests that must be completed. ! 6335: * ! 6336: * 'done_scp' will always be NULL on the first iteration ! 6337: * of this loop. 'last_scp' is set at the same time as ! 6338: * 'done_scp'. ! 6339: */ ! 6340: if (done_scp == NULL) { ! 6341: done_scp = asc_dequeue_list(&boardp->done, &last_scp, ! 6342: ASC_TID_ALL); ! 6343: } else { ! 6344: ASC_ASSERT(last_scp != NULL); ! 6345: REQPNEXT(last_scp) = asc_dequeue_list(&boardp->done, ! 6346: &new_last_scp, ASC_TID_ALL); ! 6347: if (new_last_scp != NULL) { ! 6348: ASC_ASSERT(REQPNEXT(last_scp) != NULL); ! 6349: last_scp = new_last_scp; ! 6350: } ! 6351: } ! 6352: } ! 6353: } ! 6354: ! 6355: /* Interrupts could be enabled here. */ ! 6356: ! 6357: /* ! 6358: * It is possible for the request done function to re-enable ! 6359: * interrupts without confusing the driver. But here the ! 6360: * original flags aren't restored until all requests have been ! 6361: * completed. ! 6362: */ ! 6363: asc_scsi_done_list(done_scp); ! 6364: ! 6365: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,95) ! 6366: /* ! 6367: * Restore the original flags which will enable interrupts ! 6368: * if and only if they were enabled on entry. ! 6369: */ ! 6370: restore_flags(flags); ! 6371: #else /* version >= v2.1.95 */ ! 6372: /* ! 6373: * Release the I/O spinlock and restore the original flags ! 6374: * which will enable interrupts if and only if they were ! 6375: * enabled on entry. ! 6376: */ ! 6377: spin_unlock_irqrestore(&io_request_lock, flags); ! 6378: #endif /* version >= v2.1.95 */ ! 6379: ! 6380: ASC_DBG(1, "advansys_interrupt: end\n"); ! 6381: return; ! 6382: } ! 6383: ! 6384: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 6385: /* ! 6386: * Set the number of commands to queue per device for the ! 6387: * specified host adapter. ! 6388: */ ! 6389: STATIC void ! 6390: advansys_select_queue_depths(struct Scsi_Host *shp, Scsi_Device *devicelist) ! 6391: { ! 6392: Scsi_Device *device; ! 6393: asc_board_t *boardp; ! 6394: ! 6395: boardp = ASC_BOARDP(shp); ! 6396: boardp->flags |= ASC_SELECT_QUEUE_DEPTHS; ! 6397: for (device = devicelist; device != NULL; device = device->next) { ! 6398: if (device->host != shp) { ! 6399: continue; ! 6400: } ! 6401: /* ! 6402: * Save a pointer to the device and set its initial/maximum ! 6403: * queue depth. ! 6404: */ ! 6405: boardp->device[device->id] = device; ! 6406: if (ASC_NARROW_BOARD(boardp)) { ! 6407: device->queue_depth = ! 6408: boardp->dvc_var.asc_dvc_var.max_dvc_qng[device->id]; ! 6409: } else { ! 6410: device->queue_depth = ! 6411: boardp->dvc_var.adv_dvc_var.max_dvc_qng; ! 6412: } ! 6413: ASC_DBG3(1, "advansys_select_queue_depths: shp %x, id %d, depth %d\n", ! 6414: (unsigned) shp, device->id, device->queue_depth); ! 6415: } ! 6416: } ! 6417: #endif /* version >= v1.3.89 */ ! 6418: ! 6419: /* ! 6420: * Function used only with polled I/O requests that are initiated by ! 6421: * advansys_command(). ! 6422: */ ! 6423: STATIC void ! 6424: advansys_command_done(Scsi_Cmnd *scp) ! 6425: { ! 6426: ASC_DBG1(1, "advansys_command_done: scp %x\n", (unsigned) scp); ! 6427: scp->SCp.Status = 1; ! 6428: } ! 6429: ! 6430: /* ! 6431: * Complete all requests on the singly linked list pointed ! 6432: * to by 'scp'. ! 6433: * ! 6434: * Interrupts can be enabled on entry. ! 6435: */ ! 6436: STATIC void ! 6437: asc_scsi_done_list(Scsi_Cmnd *scp) ! 6438: { ! 6439: Scsi_Cmnd *tscp; ! 6440: ! 6441: ASC_DBG(2, "asc_scsi_done_list: begin\n"); ! 6442: while (scp != NULL) { ! 6443: ASC_DBG1(3, "asc_scsi_done_list: scp %x\n", (unsigned) scp); ! 6444: tscp = REQPNEXT(scp); ! 6445: REQPNEXT(scp) = NULL; ! 6446: ASC_STATS(scp->host, done); ! 6447: ASC_ASSERT(scp->scsi_done != NULL); ! 6448: scp->scsi_done(scp); ! 6449: scp = tscp; ! 6450: } ! 6451: ASC_DBG(2, "asc_scsi_done_list: done\n"); ! 6452: return; ! 6453: } ! 6454: ! 6455: /* ! 6456: * Execute a single 'Scsi_Cmnd'. ! 6457: * ! 6458: * The function 'done' is called when the request has been completed. ! 6459: * ! 6460: * Scsi_Cmnd: ! 6461: * ! 6462: * host - board controlling device ! 6463: * device - device to send command ! 6464: * target - target of device ! 6465: * lun - lun of device ! 6466: * cmd_len - length of SCSI CDB ! 6467: * cmnd - buffer for SCSI 8, 10, or 12 byte CDB ! 6468: * use_sg - if non-zero indicates scatter-gather request with use_sg elements ! 6469: * ! 6470: * if (use_sg == 0) { ! 6471: * request_buffer - buffer address for request ! 6472: * request_bufflen - length of request buffer ! 6473: * } else { ! 6474: * request_buffer - pointer to scatterlist structure ! 6475: * } ! 6476: * ! 6477: * sense_buffer - sense command buffer ! 6478: * ! 6479: * result (4 bytes of an int): ! 6480: * Byte Meaning ! 6481: * 0 SCSI Status Byte Code ! 6482: * 1 SCSI One Byte Message Code ! 6483: * 2 Host Error Code ! 6484: * 3 Mid-Level Error Code ! 6485: * ! 6486: * host driver fields: ! 6487: * SCp - Scsi_Pointer used for command processing status ! 6488: * scsi_done - used to save caller's done function ! 6489: * host_scribble - used for pointer to another Scsi_Cmnd ! 6490: * ! 6491: * If this function returns ASC_NOERROR or ASC_ERROR the request ! 6492: * has been enqueued on the board's 'done' queue and must be ! 6493: * completed by the caller. ! 6494: * ! 6495: * If ASC_BUSY is returned the request must be enqueued by the ! 6496: * caller and re-tried later. ! 6497: */ ! 6498: STATIC int ! 6499: asc_execute_scsi_cmnd(Scsi_Cmnd *scp) ! 6500: { ! 6501: asc_board_t *boardp; ! 6502: ASC_DVC_VAR *asc_dvc_varp; ! 6503: ADV_DVC_VAR *adv_dvc_varp; ! 6504: ADV_SCSI_REQ_Q *adv_scsiqp; ! 6505: Scsi_Device *device; ! 6506: int ret; ! 6507: ! 6508: ASC_ASSERT(interrupts_enabled() == ASC_FALSE); ! 6509: ASC_DBG2(1, "asc_execute_scsi_cmnd: scp %x, done %x\n", ! 6510: (unsigned) scp, (unsigned) scp->scsi_done); ! 6511: ! 6512: boardp = ASC_BOARDP(scp->host); ! 6513: device = boardp->device[scp->target]; ! 6514: ! 6515: if (ASC_NARROW_BOARD(boardp)) { ! 6516: /* ! 6517: * Build and execute Narrow Board request. ! 6518: */ ! 6519: ! 6520: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; ! 6521: ! 6522: /* ! 6523: * Build Asc Library request structure using the ! 6524: * global structures 'asc_scsi_req' and 'asc_sg_head'. ! 6525: * ! 6526: * asc_build_req() can not return ASC_BUSY. ! 6527: */ ! 6528: if (asc_build_req(boardp, scp) == ASC_ERROR) { ! 6529: ASC_STATS(scp->host, build_error); ! 6530: return ASC_ERROR; ! 6531: } ! 6532: ! 6533: /* ! 6534: * Execute the command. If there is no error, add the command ! 6535: * to the active queue. ! 6536: */ ! 6537: switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) { ! 6538: case ASC_NOERROR: ! 6539: ASC_STATS(scp->host, exe_noerror); ! 6540: /* ! 6541: * Increment monotonically increasing per device successful ! 6542: * request counter. Wrapping doesn't matter. ! 6543: */ ! 6544: boardp->reqcnt[scp->target]++; ! 6545: ! 6546: #if ASC_QUEUE_FLOW_CONTROL ! 6547: /* ! 6548: * Conditionally increment the device queue depth. ! 6549: * ! 6550: * If no error occurred and there have been 100 consecutive ! 6551: * successful requests and the current queue depth is less ! 6552: * than the maximum queue depth, then increment the current ! 6553: * queue depth. ! 6554: */ ! 6555: if (boardp->nerrcnt[scp->target]++ > 100) { ! 6556: boardp->nerrcnt[scp->target] = 0; ! 6557: if (device != NULL && ! 6558: (device->queue_curr_depth < device->queue_depth) && ! 6559: (!(boardp->queue_full & ! 6560: ADV_TID_TO_TIDMASK(scp->target)) || ! 6561: (boardp->queue_full_cnt[scp->target] > ! 6562: device->queue_curr_depth))) { ! 6563: device->queue_curr_depth++; ! 6564: } ! 6565: } ! 6566: #endif /* ASC_QUEUE_FLOW_CONTROL */ ! 6567: asc_enqueue(&boardp->active, scp, ASC_BACK); ! 6568: ASC_DBG(1, ! 6569: "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n"); ! 6570: break; ! 6571: case ASC_BUSY: ! 6572: /* Caller must enqueue request and retry later. */ ! 6573: ASC_STATS(scp->host, exe_busy); ! 6574: #if ASC_QUEUE_FLOW_CONTROL ! 6575: /* ! 6576: * Clear consecutive no error counter and if possible decrement ! 6577: * queue depth. ! 6578: */ ! 6579: boardp->nerrcnt[scp->target] = 0; ! 6580: if (device != NULL && device->queue_curr_depth > 1) { ! 6581: device->queue_curr_depth--; ! 6582: } ! 6583: #endif /* ASC_QUEUE_FLOW_CONTROL */ ! 6584: break; ! 6585: case ASC_ERROR: ! 6586: ASC_PRINT2( ! 6587: "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code %x\n", ! 6588: boardp->id, asc_dvc_varp->err_code); ! 6589: ASC_STATS(scp->host, exe_error); ! 6590: #if ASC_QUEUE_FLOW_CONTROL ! 6591: /* Clear consecutive no error counter. */ ! 6592: boardp->nerrcnt[scp->target] = 0; ! 6593: #endif /* ASC_QUEUE_FLOW_CONTROL */ ! 6594: scp->result = HOST_BYTE(DID_ERROR); ! 6595: asc_enqueue(&boardp->done, scp, ASC_BACK); ! 6596: break; ! 6597: default: ! 6598: ASC_PRINT2( ! 6599: "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code %x\n", ! 6600: boardp->id, asc_dvc_varp->err_code); ! 6601: ASC_STATS(scp->host, exe_unknown); ! 6602: #if ASC_QUEUE_FLOW_CONTROL ! 6603: /* Clear consecutive no error counter. */ ! 6604: boardp->nerrcnt[scp->target] = 0; ! 6605: #endif /* ASC_QUEUE_FLOW_CONTROL */ ! 6606: scp->result = HOST_BYTE(DID_ERROR); ! 6607: asc_enqueue(&boardp->done, scp, ASC_BACK); ! 6608: break; ! 6609: } ! 6610: } else { ! 6611: /* ! 6612: * Build and execute Wide Board request. ! 6613: */ ! 6614: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; ! 6615: ! 6616: /* ! 6617: * Build and get a pointer to an Adv Library request structure. ! 6618: * ! 6619: * If the request is successfully built then send it below, ! 6620: * otherwise return with an error. ! 6621: */ ! 6622: switch (adv_build_req(boardp, scp, &adv_scsiqp)) { ! 6623: case ASC_NOERROR: ! 6624: ASC_DBG(3, "asc_execute_scsi_cmnd: adv_build_req ASC_NOERROR\n"); ! 6625: break; ! 6626: case ASC_BUSY: ! 6627: ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_BUSY\n"); ! 6628: return ASC_BUSY; ! 6629: case ASC_ERROR: ! 6630: default: ! 6631: ASC_DBG(1, "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n"); ! 6632: ASC_STATS(scp->host, build_error); ! 6633: return ASC_ERROR; ! 6634: } ! 6635: ! 6636: /* ! 6637: * Execute the command. If there is no error, add the command ! 6638: * to the active queue. ! 6639: */ ! 6640: switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) { ! 6641: case ASC_NOERROR: ! 6642: ASC_STATS(scp->host, exe_noerror); ! 6643: /* ! 6644: * Increment monotonically increasing per device successful ! 6645: * request counter. Wrapping doesn't matter. ! 6646: */ ! 6647: boardp->reqcnt[scp->target]++; ! 6648: asc_enqueue(&boardp->active, scp, ASC_BACK); ! 6649: ASC_DBG(1, ! 6650: "asc_execute_scsi_cmnd: AdvExeScsiQueue(), ASC_NOERROR\n"); ! 6651: break; ! 6652: case ASC_BUSY: ! 6653: /* Caller must enqueue request and retry later. */ ! 6654: ASC_STATS(scp->host, exe_busy); ! 6655: break; ! 6656: case ASC_ERROR: ! 6657: ASC_PRINT2( ! 6658: "asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() ASC_ERROR, err_code %x\n", ! 6659: boardp->id, adv_dvc_varp->err_code); ! 6660: ASC_STATS(scp->host, exe_error); ! 6661: scp->result = HOST_BYTE(DID_ERROR); ! 6662: asc_enqueue(&boardp->done, scp, ASC_BACK); ! 6663: break; ! 6664: default: ! 6665: ASC_PRINT2( ! 6666: "asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() unknown, err_code %x\n", ! 6667: boardp->id, adv_dvc_varp->err_code); ! 6668: ASC_STATS(scp->host, exe_unknown); ! 6669: scp->result = HOST_BYTE(DID_ERROR); ! 6670: asc_enqueue(&boardp->done, scp, ASC_BACK); ! 6671: break; ! 6672: } ! 6673: } ! 6674: ! 6675: ASC_DBG(1, "asc_execute_scsi_cmnd: end\n"); ! 6676: ASC_ASSERT(interrupts_enabled() == ASC_FALSE); ! 6677: return ret; ! 6678: } ! 6679: ! 6680: /* ! 6681: * Build a request structure for the Asc Library (Narrow Board). ! 6682: * ! 6683: * The global structures 'asc_scsi_q' and 'asc_sg_head' are ! 6684: * used to build the request. ! 6685: * ! 6686: * If an error occurs, then return ASC_ERROR. ! 6687: */ ! 6688: STATIC int ! 6689: asc_build_req(asc_board_t *boardp, Scsi_Cmnd *scp) ! 6690: { ! 6691: /* ! 6692: * Mutually exclusive access is required to 'asc_scsi_q' and ! 6693: * 'asc_sg_head' until after the request is started. ! 6694: */ ! 6695: memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q)); ! 6696: ! 6697: /* ! 6698: * Point the ASC_SCSI_Q to the 'Scsi_Cmnd'. ! 6699: */ ! 6700: asc_scsi_q.q2.srb_ptr = (ulong) scp; ! 6701: ! 6702: /* ! 6703: * Build the ASC_SCSI_Q request. ! 6704: */ ! 6705: ASC_ASSERT(scp->cmd_len <= ASC_MAX_CDB_LEN); ! 6706: if (scp->cmd_len > ASC_MAX_CDB_LEN) { ! 6707: scp->cmd_len = ASC_MAX_CDB_LEN; ! 6708: } ! 6709: asc_scsi_q.cdbptr = &scp->cmnd[0]; ! 6710: asc_scsi_q.q2.cdb_len = scp->cmd_len; ! 6711: asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target); ! 6712: asc_scsi_q.q1.target_lun = scp->lun; ! 6713: asc_scsi_q.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun); ! 6714: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0) ! 6715: asc_scsi_q.q1.sense_addr = (ulong) &scp->sense_buffer[0]; ! 6716: #else /* version >= v2.0.0 */ ! 6717: asc_scsi_q.q1.sense_addr = virt_to_bus(&scp->sense_buffer[0]); ! 6718: #endif /* version >= v2.0.0 */ ! 6719: asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer); ! 6720: ! 6721: /* ! 6722: * If there are any outstanding requests for the current target, ! 6723: * then every 255th request send an ORDERED request. This heuristic ! 6724: * tries to retain the benefit of request sorting while preventing ! 6725: * request starvation. 255 is the max number of tags or pending commands ! 6726: * a device may have outstanding. ! 6727: * ! 6728: * The request count is incremented below for every successfully ! 6729: * started request. ! 6730: * ! 6731: */ ! 6732: if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->target] > 0) && ! 6733: (boardp->reqcnt[scp->target] % 255) == 0) { ! 6734: asc_scsi_q.q2.tag_code = M2_QTAG_MSG_ORDERED; ! 6735: } else { ! 6736: asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE; ! 6737: } ! 6738: ! 6739: /* ! 6740: * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather ! 6741: * buffer command. ! 6742: */ ! 6743: if (scp->use_sg == 0) { ! 6744: /* ! 6745: * CDB request of single contiguous buffer. ! 6746: */ ! 6747: ASC_STATS(scp->host, cont_cnt); ! 6748: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0) ! 6749: asc_scsi_q.q1.data_addr = (ulong) scp->request_buffer; ! 6750: #else /* version >= v2.0.0 */ ! 6751: asc_scsi_q.q1.data_addr = virt_to_bus(scp->request_buffer); ! 6752: #endif /* version >= v2.0.0 */ ! 6753: asc_scsi_q.q1.data_cnt = scp->request_bufflen; ! 6754: ASC_STATS_ADD(scp->host, cont_xfer, ! 6755: ASC_CEILING(scp->request_bufflen, 512)); ! 6756: asc_scsi_q.q1.sg_queue_cnt = 0; ! 6757: asc_scsi_q.sg_head = NULL; ! 6758: } else { ! 6759: /* ! 6760: * CDB scatter-gather request list. ! 6761: */ ! 6762: int sgcnt; ! 6763: struct scatterlist *slp; ! 6764: ! 6765: if (scp->use_sg > scp->host->sg_tablesize) { ! 6766: ASC_PRINT3( ! 6767: "asc_build_req: board %d: use_sg %d > sg_tablesize %d\n", ! 6768: boardp->id, scp->use_sg, scp->host->sg_tablesize); ! 6769: scp->result = HOST_BYTE(DID_ERROR); ! 6770: asc_enqueue(&boardp->done, scp, ASC_BACK); ! 6771: return ASC_ERROR; ! 6772: } ! 6773: ! 6774: ASC_STATS(scp->host, sg_cnt); ! 6775: ! 6776: /* ! 6777: * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q ! 6778: * structure to point to it. ! 6779: */ ! 6780: memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD)); ! 6781: ! 6782: asc_scsi_q.q1.cntl |= QC_SG_HEAD; ! 6783: asc_scsi_q.sg_head = &asc_sg_head; ! 6784: asc_scsi_q.q1.data_cnt = 0; ! 6785: asc_scsi_q.q1.data_addr = 0; ! 6786: asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = scp->use_sg; ! 6787: ASC_STATS_ADD(scp->host, sg_elem, asc_sg_head.entry_cnt); ! 6788: ! 6789: /* ! 6790: * Convert scatter-gather list into ASC_SG_HEAD list. ! 6791: */ ! 6792: slp = (struct scatterlist *) scp->request_buffer; ! 6793: for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) { ! 6794: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0) ! 6795: asc_sg_head.sg_list[sgcnt].addr = (ulong) slp->address; ! 6796: #else /* version >= v2.0.0 */ ! 6797: asc_sg_head.sg_list[sgcnt].addr = virt_to_bus(slp->address); ! 6798: #endif /* version >= v2.0.0 */ ! 6799: asc_sg_head.sg_list[sgcnt].bytes = slp->length; ! 6800: ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512)); ! 6801: } ! 6802: } ! 6803: ! 6804: ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q); ! 6805: ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); ! 6806: ! 6807: return ASC_NOERROR; ! 6808: } ! 6809: ! 6810: /* ! 6811: * Build a request structure for the Adv Library (Wide Board). ! 6812: * ! 6813: * If an adv_req_t can not be allocated to issue the request, ! 6814: * then return ASC_BUSY. If an error occurs, then return ASC_ERROR. ! 6815: */ ! 6816: STATIC int ! 6817: adv_build_req(asc_board_t *boardp, Scsi_Cmnd *scp, ! 6818: ADV_SCSI_REQ_Q **adv_scsiqpp) ! 6819: { ! 6820: adv_req_t *reqp; ! 6821: ADV_SCSI_REQ_Q *scsiqp; ! 6822: int i; ! 6823: ! 6824: /* ! 6825: * Allocate an adv_req_t structure from the board to execute ! 6826: * the command. ! 6827: */ ! 6828: if (boardp->adv_reqp == NULL) { ! 6829: ASC_DBG(1, "adv_build_req: no free adv_req_t\n"); ! 6830: ASC_STATS(scp->host, adv_build_noreq); ! 6831: return ASC_BUSY; ! 6832: } else { ! 6833: reqp = boardp->adv_reqp; ! 6834: boardp->adv_reqp = reqp->next_reqp; ! 6835: reqp->next_reqp = NULL; ! 6836: } ! 6837: ! 6838: /* ! 6839: * Get 4-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers. ! 6840: */ ! 6841: scsiqp = (ADV_SCSI_REQ_Q *) ADV_DWALIGN(&reqp->scsi_req_q); ! 6842: memset(scsiqp, 0, sizeof(ADV_SCSI_REQ_Q)); ! 6843: ! 6844: /* ! 6845: * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure. ! 6846: */ ! 6847: scsiqp->srb_ptr = (ulong) reqp; ! 6848: ! 6849: /* ! 6850: * Set the adv_req_t 'cmndp' to point to the Scsi_Cmnd structure. ! 6851: */ ! 6852: reqp->cmndp = scp; ! 6853: ! 6854: /* ! 6855: * Build the ADV_SCSI_REQ_Q request. ! 6856: */ ! 6857: ! 6858: /* ! 6859: * Set CDB length and copy it to the request structure. ! 6860: */ ! 6861: ASC_ASSERT(scp->cmd_len <= ASC_MAX_CDB_LEN); ! 6862: if (scp->cmd_len > ASC_MAX_CDB_LEN) { ! 6863: scp->cmd_len = ASC_MAX_CDB_LEN; ! 6864: } ! 6865: scsiqp->cdb_len = scp->cmd_len; ! 6866: for (i = 0; i < scp->cmd_len; i++) { ! 6867: scsiqp->cdb[i] = scp->cmnd[i]; ! 6868: } ! 6869: ! 6870: scsiqp->target_id = scp->target; ! 6871: scsiqp->target_lun = scp->lun; ! 6872: ! 6873: scsiqp->vsense_addr = (ulong) &scp->sense_buffer[0]; ! 6874: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0) ! 6875: scsiqp->sense_addr = (ulong) &scp->sense_buffer[0]; ! 6876: #else /* version >= v2.0.0 */ ! 6877: scsiqp->sense_addr = virt_to_bus(&scp->sense_buffer[0]); ! 6878: #endif /* version >= v2.0.0 */ ! 6879: scsiqp->sense_len = sizeof(scp->sense_buffer); ! 6880: ! 6881: /* ! 6882: * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather ! 6883: * buffer command. ! 6884: */ ! 6885: scsiqp->data_cnt = scp->request_bufflen; ! 6886: scsiqp->vdata_addr = (ulong) scp->request_buffer; ! 6887: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0) ! 6888: scsiqp->data_addr = (ulong) scp->request_buffer; ! 6889: #else /* version >= v2.0.0 */ ! 6890: scsiqp->data_addr = virt_to_bus(scp->request_buffer); ! 6891: #endif /* version >= v2.0.0 */ ! 6892: ! 6893: if (scp->use_sg == 0) { ! 6894: /* ! 6895: * CDB request of single contiguous buffer. ! 6896: */ ! 6897: reqp->sgblkp = NULL; ! 6898: scsiqp->sg_list_ptr = NULL; ! 6899: ASC_STATS(scp->host, cont_cnt); ! 6900: ASC_STATS_ADD(scp->host, cont_xfer, ! 6901: ASC_CEILING(scp->request_bufflen, 512)); ! 6902: } else { ! 6903: /* ! 6904: * CDB scatter-gather request list. ! 6905: */ ! 6906: if (scp->use_sg > ADV_MAX_SG_LIST) { ! 6907: ASC_PRINT3( ! 6908: "adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n", ! 6909: boardp->id, scp->use_sg, scp->host->sg_tablesize); ! 6910: scp->result = HOST_BYTE(DID_ERROR); ! 6911: asc_enqueue(&boardp->done, scp, ASC_BACK); ! 6912: ! 6913: /* ! 6914: * Free the 'adv_req_t' structure by adding it back to the ! 6915: * board free list. ! 6916: */ ! 6917: reqp->next_reqp = boardp->adv_reqp; ! 6918: boardp->adv_reqp = reqp; ! 6919: ! 6920: return ASC_ERROR; ! 6921: } ! 6922: ! 6923: /* ! 6924: * Allocate an 'adv_sgblk_t' structure from the board to ! 6925: * execute the command. ! 6926: */ ! 6927: if (boardp->adv_sgblkp == NULL) { ! 6928: ASC_DBG(1, "adv_build_req: no free adv_sgblk_t\n"); ! 6929: ASC_STATS(scp->host, adv_build_nosg); ! 6930: /* ! 6931: * Free the 'adv_req_t' structure by adding it back to the ! 6932: * board free list. ! 6933: */ ! 6934: reqp->next_reqp = boardp->adv_reqp; ! 6935: boardp->adv_reqp = reqp; ! 6936: return ASC_BUSY; ! 6937: } else { ! 6938: reqp->sgblkp = boardp->adv_sgblkp; ! 6939: boardp->adv_sgblkp = reqp->sgblkp->next_sgblkp; ! 6940: reqp->sgblkp->next_sgblkp = NULL; ! 6941: } ! 6942: ! 6943: /* ! 6944: * Build scatter-gather list. ! 6945: */ ! 6946: scsiqp->sg_list_ptr = (ADV_SG_BLOCK *) ! 6947: ADV_DWALIGN(&reqp->sgblkp->sg_block[0]); ! 6948: ! 6949: memset(scsiqp->sg_list_ptr, 0, sizeof(ADV_SG_BLOCK) * ! 6950: (ADV_NUM_SG_BLOCK + ADV_NUM_PAGE_CROSSING)); ! 6951: ! 6952: if (adv_get_sglist(&boardp->dvc_var.adv_dvc_var, scsiqp, scp) == ! 6953: ADV_ERROR) { ! 6954: ! 6955: /* ! 6956: * Free the adv_sgblk_t structure, if any, by adding it back ! 6957: * to the board free list. ! 6958: */ ! 6959: ASC_ASSERT(reqp->sgblkp != NULL); ! 6960: reqp->sgblkp->next_sgblkp = boardp->adv_sgblkp; ! 6961: boardp->adv_sgblkp = reqp->sgblkp; ! 6962: ! 6963: /* ! 6964: * Free the adv_req_t structure by adding it back to the ! 6965: * board free list. ! 6966: */ ! 6967: reqp->next_reqp = boardp->adv_reqp; ! 6968: boardp->adv_reqp = reqp; ! 6969: ! 6970: return ADV_ERROR; ! 6971: } ! 6972: ! 6973: ASC_STATS(scp->host, sg_cnt); ! 6974: ASC_STATS_ADD(scp->host, sg_elem, scp->use_sg); ! 6975: } ! 6976: ! 6977: ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); ! 6978: ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); ! 6979: ! 6980: *adv_scsiqpp = scsiqp; ! 6981: ! 6982: return ASC_NOERROR; ! 6983: } ! 6984: ! 6985: /* ! 6986: * Build scatter-gather list for Adv Library (Wide Board). ! 6987: * ! 6988: * Return: ! 6989: * ADV_SUCCESS(1) - SG List successfully created ! 6990: * ADV_ERROR(-1) - SG List creation failed ! 6991: */ ! 6992: STATIC int ! 6993: adv_get_sglist(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp, ! 6994: Scsi_Cmnd *scp) ! 6995: { ! 6996: ADV_SG_BLOCK *sg_block; /* virtual address of a SG */ ! 6997: ulong sg_block_next_addr; /* block and its next */ ! 6998: ulong sg_block_physical_addr; ! 6999: int sg_block_index, i; /* how many SG entries */ ! 7000: struct scatterlist *slp; ! 7001: int sg_elem_cnt; ! 7002: ! 7003: slp = (struct scatterlist *) scp->request_buffer; ! 7004: sg_elem_cnt = scp->use_sg; ! 7005: ! 7006: sg_block = scsiqp->sg_list_ptr; ! 7007: sg_block_next_addr = (ulong) sg_block; /* allow math operation */ ! 7008: sg_block_physical_addr = ! 7009: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0) ! 7010: (ulong) scsiqp->sg_list_ptr; ! 7011: #else /* version >= v2.0.0 */ ! 7012: virt_to_bus(scsiqp->sg_list_ptr); ! 7013: #endif /* version >= v2.0.0 */ ! 7014: ADV_ASSERT(ADV_DWALIGN(sg_block_physical_addr) == ! 7015: sg_block_physical_addr); ! 7016: scsiqp->sg_real_addr = sg_block_physical_addr; ! 7017: ! 7018: sg_block_index = 0; ! 7019: do ! 7020: { ! 7021: sg_block->first_entry_no = sg_block_index; ! 7022: for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) ! 7023: { ! 7024: sg_block->sg_list[i].sg_addr = ! 7025: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0) ! 7026: (ulong) slp->address; ! 7027: #else /* version >= v2.0.0 */ ! 7028: virt_to_bus(slp->address); ! 7029: #endif /* version >= v2.0.0 */ ! 7030: sg_block->sg_list[i].sg_count = slp->length; ! 7031: ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512)); ! 7032: ! 7033: if (--sg_elem_cnt == 0) ! 7034: { /* last entry, get out */ ! 7035: scsiqp->sg_entry_cnt = sg_block_index + i + 1; ! 7036: sg_block->last_entry_no = sg_block_index + i; ! 7037: sg_block->sg_ptr = 0L; /* next link = NULL */ ! 7038: return ADV_SUCCESS; ! 7039: } ! 7040: slp++; ! 7041: } ! 7042: sg_block_next_addr += sizeof(ADV_SG_BLOCK); ! 7043: sg_block_physical_addr += sizeof(ADV_SG_BLOCK); ! 7044: ADV_ASSERT(ADV_DWALIGN(sg_block_physical_addr) == ! 7045: sg_block_physical_addr); ! 7046: ! 7047: sg_block_index += NO_OF_SG_PER_BLOCK; ! 7048: sg_block->sg_ptr = (ADV_SG_BLOCK *) sg_block_physical_addr; ! 7049: sg_block->last_entry_no = sg_block_index - 1; ! 7050: sg_block = (ADV_SG_BLOCK *) sg_block_next_addr; /* virtual addr */ ! 7051: } ! 7052: while (1); ! 7053: /* NOTREACHED */ ! 7054: } ! 7055: ! 7056: /* ! 7057: * asc_isr_callback() - Second Level Interrupt Handler called by AscISR(). ! 7058: * ! 7059: * Interrupt callback function for the Narrow SCSI Asc Library. ! 7060: */ ! 7061: STATIC void ! 7062: asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep) ! 7063: { ! 7064: asc_board_t *boardp; ! 7065: Scsi_Cmnd *scp; ! 7066: struct Scsi_Host *shp; ! 7067: int underrun = ASC_FALSE; ! 7068: int i; ! 7069: ! 7070: ASC_ASSERT(interrupts_enabled() == ASC_FALSE); ! 7071: ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp %x, qdonep %x\n", ! 7072: (unsigned) asc_dvc_varp, (unsigned) qdonep); ! 7073: ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep); ! 7074: ! 7075: /* ! 7076: * Get the Scsi_Cmnd structure and Scsi_Host structure for the ! 7077: * command that has been completed. ! 7078: */ ! 7079: scp = (Scsi_Cmnd *) qdonep->d2.srb_ptr; ! 7080: ASC_DBG1(1, "asc_isr_callback: scp %x\n", (unsigned) scp); ! 7081: ! 7082: if (scp == NULL) { ! 7083: ASC_PRINT("asc_isr_callback: scp is NULL\n"); ! 7084: return; ! 7085: } ! 7086: ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); ! 7087: ! 7088: /* ! 7089: * If the request's host pointer is not valid, display a ! 7090: * message and return. ! 7091: */ ! 7092: shp = scp->host; ! 7093: for (i = 0; i < asc_board_count; i++) { ! 7094: if (asc_host[i] == shp) { ! 7095: break; ! 7096: } ! 7097: } ! 7098: if (i == asc_board_count) { ! 7099: ASC_PRINT2("asc_isr_callback: scp %x has bad host pointer, host %x\n", ! 7100: (unsigned) scp, (unsigned) shp); ! 7101: return; ! 7102: } ! 7103: ! 7104: ASC_STATS(shp, callback); ! 7105: ASC_DBG1(1, "asc_isr_callback: shp %x\n", (unsigned) shp); ! 7106: ! 7107: /* ! 7108: * If the request isn't found on the active queue, it may ! 7109: * have been removed to handle a reset or abort request. ! 7110: * Display a message and return. ! 7111: */ ! 7112: boardp = ASC_BOARDP(shp); ! 7113: ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var); ! 7114: if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) { ! 7115: ASC_PRINT2("asc_isr_callback: board %d: scp %x not on active queue\n", ! 7116: boardp->id, (unsigned) scp); ! 7117: return; ! 7118: } ! 7119: ! 7120: /* ! 7121: * Check for an underrun condition. ! 7122: */ ! 7123: if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 && ! 7124: qdonep->remain_bytes <= scp->request_bufflen != 0) { ! 7125: ASC_DBG1(1, "asc_isr_callback: underrun condition %u bytes\n", ! 7126: (unsigned) qdonep->remain_bytes); ! 7127: underrun = ASC_TRUE; ! 7128: } ! 7129: ! 7130: /* ! 7131: * 'qdonep' contains the command's ending status. ! 7132: */ ! 7133: switch (qdonep->d3.done_stat) { ! 7134: case QD_NO_ERROR: ! 7135: ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n"); ! 7136: switch (qdonep->d3.host_stat) { ! 7137: case QHSTA_NO_ERROR: ! 7138: scp->result = 0; ! 7139: break; ! 7140: default: ! 7141: /* QHSTA error occurred */ ! 7142: scp->result = HOST_BYTE(DID_ERROR); ! 7143: break; ! 7144: } ! 7145: ! 7146: /* ! 7147: * If an INQUIRY command completed successfully, then call ! 7148: * the AscInquiryHandling() function to set-up the device. ! 7149: */ ! 7150: if (scp->cmnd[0] == SCSICMD_Inquiry && scp->lun == 0 && ! 7151: (scp->request_bufflen - qdonep->remain_bytes) >= 8) ! 7152: { ! 7153: AscInquiryHandling(asc_dvc_varp, scp->target & 0x7, ! 7154: (ASC_SCSI_INQUIRY *) scp->request_buffer); ! 7155: } ! 7156: ! 7157: /* ! 7158: * If there was an underrun without any other error, ! 7159: * set DID_ERROR to indicate the underrun error. ! 7160: * ! 7161: * Note: There is no way yet to indicate the number ! 7162: * of underrun bytes. ! 7163: */ ! 7164: if (scp->result == 0 && underrun == ASC_TRUE) { ! 7165: scp->result = HOST_BYTE(DID_UNDERRUN); ! 7166: } ! 7167: break; ! 7168: ! 7169: case QD_WITH_ERROR: ! 7170: ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n"); ! 7171: switch (qdonep->d3.host_stat) { ! 7172: case QHSTA_NO_ERROR: ! 7173: if (qdonep->d3.scsi_stat == SS_CHK_CONDITION) { ! 7174: ASC_DBG(2, "asc_isr_callback: SS_CHK_CONDITION\n"); ! 7175: ASC_DBG_PRT_SENSE(2, scp->sense_buffer, ! 7176: sizeof(scp->sense_buffer)); ! 7177: /* ! 7178: * Note: The 'status_byte()' macro used by target drivers ! 7179: * defined in scsi.h shifts the status byte returned by ! 7180: * host drivers right by 1 bit. This is why target drivers ! 7181: * also use right shifted status byte definitions. For ! 7182: * instance target drivers use CHECK_CONDITION, defined to ! 7183: * 0x1, instead of the SCSI defined check condition value ! 7184: * of 0x2. Host drivers are supposed to return the status ! 7185: * byte as it is defined by SCSI. ! 7186: */ ! 7187: scp->result = DRIVER_BYTE(DRIVER_SENSE) | ! 7188: STATUS_BYTE(qdonep->d3.scsi_stat); ! 7189: } else { ! 7190: scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); ! 7191: } ! 7192: break; ! 7193: ! 7194: default: ! 7195: /* QHSTA error occurred */ ! 7196: ASC_DBG1(1, "asc_isr_callback: host_stat %x\n", ! 7197: qdonep->d3.host_stat); ! 7198: scp->result = HOST_BYTE(DID_BAD_TARGET); ! 7199: break; ! 7200: } ! 7201: break; ! 7202: ! 7203: case QD_ABORTED_BY_HOST: ! 7204: ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n"); ! 7205: scp->result = HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3.scsi_msg) | ! 7206: STATUS_BYTE(qdonep->d3.scsi_stat); ! 7207: break; ! 7208: ! 7209: default: ! 7210: ASC_DBG1(1, "asc_isr_callback: done_stat %x\n", qdonep->d3.done_stat); ! 7211: scp->result = HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3.scsi_msg) | ! 7212: STATUS_BYTE(qdonep->d3.scsi_stat); ! 7213: break; ! 7214: } ! 7215: ! 7216: /* ! 7217: * If the 'init_tidmask' bit isn't already set for the target and the ! 7218: * current request finished normally, then set the bit for the target ! 7219: * to indicate that a device is present. ! 7220: */ ! 7221: if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 && ! 7222: qdonep->d3.done_stat == QD_NO_ERROR && ! 7223: qdonep->d3.host_stat == QHSTA_NO_ERROR) { ! 7224: boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target); ! 7225: } ! 7226: ! 7227: /* ! 7228: * Because interrupts may be enabled by the 'Scsi_Cmnd' done ! 7229: * function, add the command to the end of the board's done queue. ! 7230: * The done function for the command will be called from ! 7231: * advansys_interrupt(). ! 7232: */ ! 7233: asc_enqueue(&boardp->done, scp, ASC_BACK); ! 7234: ! 7235: return; ! 7236: } ! 7237: ! 7238: /* ! 7239: * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR(). ! 7240: * ! 7241: * Callback function for the Wide SCSI Adv Library. ! 7242: */ ! 7243: STATIC void ! 7244: adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp) ! 7245: { ! 7246: asc_board_t *boardp; ! 7247: adv_req_t *reqp; ! 7248: Scsi_Cmnd *scp; ! 7249: struct Scsi_Host *shp; ! 7250: int underrun = ASC_FALSE; ! 7251: int i; ! 7252: ! 7253: ASC_ASSERT(interrupts_enabled() == ASC_FALSE); ! 7254: ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp %x, scsiqp %x\n", ! 7255: (unsigned) adv_dvc_varp, (unsigned) scsiqp); ! 7256: ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); ! 7257: ! 7258: /* ! 7259: * Get the adv_req_t structure for the command that has been ! 7260: * completed. The adv_req_t structure actually contains the ! 7261: * completed ADV_SCSI_REQ_Q structure. ! 7262: */ ! 7263: reqp = (adv_req_t *) scsiqp->srb_ptr; ! 7264: ASC_DBG1(1, "adv_isr_callback: reqp %x\n", (unsigned) reqp); ! 7265: if (reqp == NULL) { ! 7266: ASC_PRINT("adv_isr_callback: reqp is NULL\n"); ! 7267: return; ! 7268: } ! 7269: ! 7270: /* ! 7271: * Get the Scsi_Cmnd structure and Scsi_Host structure for the ! 7272: * command that has been completed. ! 7273: * ! 7274: * Note: The adv_req_t request structure and adv_sgblk_t structure, ! 7275: * if any, * dropped, because a board structure pointer can not be ! 7276: * determined. ! 7277: */ ! 7278: scp = reqp->cmndp; ! 7279: ASC_DBG1(1, "adv_isr_callback: scp %x\n", (unsigned) scp); ! 7280: if (scp == NULL) { ! 7281: ASC_PRINT("adv_isr_callback: scp is NULL; adv_req_t dropped.\n"); ! 7282: return; ! 7283: } ! 7284: ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); ! 7285: ! 7286: /* ! 7287: * If the request's host pointer is not valid, display a message ! 7288: * and return. ! 7289: */ ! 7290: shp = scp->host; ! 7291: for (i = 0; i < asc_board_count; i++) { ! 7292: if (asc_host[i] == shp) { ! 7293: break; ! 7294: } ! 7295: } ! 7296: /* ! 7297: * Note: If the host structure is not found, the adv_req_t request ! 7298: * structure and adv_sgblk_t structure, if any, is dropped. ! 7299: */ ! 7300: if (i == asc_board_count) { ! 7301: ASC_PRINT2("adv_isr_callback: scp %x has bad host pointer, host %x\n", ! 7302: (unsigned) scp, (unsigned) shp); ! 7303: return; ! 7304: } ! 7305: ! 7306: ASC_STATS(shp, callback); ! 7307: ASC_DBG1(1, "adv_isr_callback: shp %x\n", (unsigned) shp); ! 7308: ! 7309: /* ! 7310: * If the request isn't found on the active queue, it may have been ! 7311: * removed to handle a reset or abort request. Display a message and ! 7312: * return. ! 7313: * ! 7314: * Note: Because the structure may still be in use don't attempt ! 7315: * to free the adv_req_t and adv_sgblk_t, if any, structures. ! 7316: */ ! 7317: boardp = ASC_BOARDP(shp); ! 7318: ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var); ! 7319: if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) { ! 7320: ASC_PRINT2("adv_isr_callback: board %d: scp %x not on active queue\n", ! 7321: boardp->id, (unsigned) scp); ! 7322: return; ! 7323: } ! 7324: ! 7325: /* ! 7326: * Check for an underrun condition. ! 7327: */ ! 7328: if (scp->request_bufflen != 0 && scsiqp->data_cnt != 0) { ! 7329: ASC_DBG1(1, "adv_isr_callback: underrun condition %lu bytes\n", ! 7330: scsiqp->data_cnt); ! 7331: underrun = ASC_TRUE; ! 7332: } ! 7333: ! 7334: /* ! 7335: * 'done_status' contains the command's ending status. ! 7336: */ ! 7337: switch (scsiqp->done_status) { ! 7338: case QD_NO_ERROR: ! 7339: ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n"); ! 7340: switch (scsiqp->host_status) { ! 7341: case QHSTA_NO_ERROR: ! 7342: scp->result = 0; ! 7343: break; ! 7344: default: ! 7345: /* QHSTA error occurred. */ ! 7346: ASC_DBG1(2, "adv_isr_callback: host_status %x\n", ! 7347: scsiqp->host_status); ! 7348: scp->result = HOST_BYTE(DID_ERROR); ! 7349: break; ! 7350: } ! 7351: /* ! 7352: * If there was an underrun without any other error, ! 7353: * set DID_ERROR to indicate the underrun error. ! 7354: * ! 7355: * Note: There is no way yet to indicate the number ! 7356: * of underrun bytes. ! 7357: */ ! 7358: if (scp->result == 0 && underrun == ASC_TRUE) { ! 7359: scp->result = HOST_BYTE(DID_UNDERRUN); ! 7360: } ! 7361: break; ! 7362: ! 7363: case QD_WITH_ERROR: ! 7364: ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n"); ! 7365: switch (scsiqp->host_status) { ! 7366: case QHSTA_NO_ERROR: ! 7367: if (scsiqp->scsi_status == SS_CHK_CONDITION) { ! 7368: ASC_DBG(2, "adv_isr_callback: SS_CHK_CONDITION\n"); ! 7369: ASC_DBG_PRT_SENSE(2, scp->sense_buffer, ! 7370: sizeof(scp->sense_buffer)); ! 7371: /* ! 7372: * Note: The 'status_byte()' macro used by target drivers ! 7373: * defined in scsi.h shifts the status byte returned by ! 7374: * host drivers right by 1 bit. This is why target drivers ! 7375: * also use right shifted status byte definitions. For ! 7376: * instance target drivers use CHECK_CONDITION, defined to ! 7377: * 0x1, instead of the SCSI defined check condition value ! 7378: * of 0x2. Host drivers are supposed to return the status ! 7379: * byte as it is defined by SCSI. ! 7380: */ ! 7381: scp->result = DRIVER_BYTE(DRIVER_SENSE) | ! 7382: STATUS_BYTE(scsiqp->scsi_status); ! 7383: } else { ! 7384: scp->result = STATUS_BYTE(scsiqp->scsi_status); ! 7385: } ! 7386: break; ! 7387: ! 7388: default: ! 7389: /* Some other QHSTA error occurred. */ ! 7390: ASC_DBG1(1, "adv_isr_callback: host_status %x\n", ! 7391: scsiqp->host_status); ! 7392: scp->result = HOST_BYTE(DID_BAD_TARGET); ! 7393: break; ! 7394: } ! 7395: break; ! 7396: ! 7397: case QD_ABORTED_BY_HOST: ! 7398: ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n"); ! 7399: scp->result = HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status); ! 7400: break; ! 7401: ! 7402: default: ! 7403: ASC_DBG1(1, "adv_isr_callback: done_status %x\n", scsiqp->done_status); ! 7404: scp->result = HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status); ! 7405: break; ! 7406: } ! 7407: ! 7408: /* ! 7409: * If the 'init_tidmask' bit isn't already set for the target and the ! 7410: * current request finished normally, then set the bit for the target ! 7411: * to indicate that a device is present. ! 7412: */ ! 7413: if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->target)) == 0 && ! 7414: scsiqp->done_status == QD_NO_ERROR && ! 7415: scsiqp->host_status == QHSTA_NO_ERROR) { ! 7416: boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->target); ! 7417: } ! 7418: ! 7419: /* ! 7420: * Because interrupts may be enabled by the 'Scsi_Cmnd' done ! 7421: * function, add the command to the end of the board's done queue. ! 7422: * The done function for the command will be called from ! 7423: * advansys_interrupt(). ! 7424: */ ! 7425: asc_enqueue(&boardp->done, scp, ASC_BACK); ! 7426: ! 7427: /* ! 7428: * Free the adv_sgblk_t structure, if any, by adding it back ! 7429: * to the board free list. ! 7430: */ ! 7431: if (reqp->sgblkp != NULL) { ! 7432: reqp->sgblkp->next_sgblkp = boardp->adv_sgblkp; ! 7433: boardp->adv_sgblkp = reqp->sgblkp; ! 7434: } ! 7435: ! 7436: /* ! 7437: * Free the adv_req_t structure used with the command by adding ! 7438: * it back to the board free list. ! 7439: */ ! 7440: reqp->next_reqp = boardp->adv_reqp; ! 7441: boardp->adv_reqp = reqp; ! 7442: ! 7443: ASC_DBG(1, "adv_isr_callback: done\n"); ! 7444: ! 7445: return; ! 7446: } ! 7447: ! 7448: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) ! 7449: #ifdef ASC_CONFIG_PCI ! 7450: /* ! 7451: * Search for an AdvanSys PCI device in the PCI configuration space. ! 7452: */ ! 7453: ASC_INITFUNC( ! 7454: STATIC int ! 7455: asc_srch_pci_dev(PCI_DEVICE *pciDevice) ! 7456: ) ! 7457: { ! 7458: int ret = PCI_DEVICE_NOT_FOUND; ! 7459: ! 7460: ASC_DBG(2, "asc_srch_pci_dev: begin\n"); ! 7461: ! 7462: if (pci_scan_method == -1) { ! 7463: pci_scan_method = asc_scan_method(); ! 7464: } ! 7465: pciDevice->type = pci_scan_method; ! 7466: ASC_DBG1(2, "asc_srch_pci_dev: type %d\n", pciDevice->type); ! 7467: ! 7468: ret = asc_pci_find_dev(pciDevice); ! 7469: ASC_DBG1(2, "asc_srch_pci_dev: asc_pci_find_dev() return %d\n", ret); ! 7470: if (ret == PCI_DEVICE_FOUND) { ! 7471: pciDevice->slotNumber = pciDevice->slotFound + 1; ! 7472: pciDevice->startSlot = pciDevice->slotFound + 1; ! 7473: } else { ! 7474: if (pciDevice->bridge > pciDevice->busNumber) { ! 7475: ASC_DBG2(2, "asc_srch_pci_dev: bridge %x, busNumber %x\n", ! 7476: pciDevice->bridge, pciDevice->busNumber); ! 7477: pciDevice->busNumber++; ! 7478: pciDevice->slotNumber = 0; ! 7479: pciDevice->startSlot = 0; ! 7480: pciDevice->endSlot = 0x0f; ! 7481: ret = asc_srch_pci_dev(pciDevice); ! 7482: ASC_DBG1(2, "asc_srch_pci_dev: recursive call return %d\n", ret); ! 7483: } ! 7484: } ! 7485: ! 7486: ASC_DBG1(2, "asc_srch_pci_dev: return %d\n", ret); ! 7487: return ret; ! 7488: } ! 7489: ! 7490: /* ! 7491: * Determine the access method to be used for 'pciDevice'. ! 7492: */ ! 7493: ASC_INITFUNC( ! 7494: STATIC uchar ! 7495: asc_scan_method(void) ! 7496: ) ! 7497: { ! 7498: ushort data; ! 7499: PCI_DATA pciData; ! 7500: uchar type; ! 7501: uchar slot; ! 7502: ! 7503: ASC_DBG(2, "asc_scan_method: begin\n"); ! 7504: memset(&pciData, 0, sizeof(pciData)); ! 7505: for (type = 1; type < 3; type++) { ! 7506: pciData.type = type; ! 7507: for (slot = 0; slot < PCI_MAX_SLOT; slot++) { ! 7508: pciData.slot = slot; ! 7509: data = asc_get_cfg_word(&pciData); ! 7510: if ((data != 0xFFFF) && (data != 0x0000)) { ! 7511: ASC_DBG2(4, "asc_scan_method: data %x, type %d\n", data, type); ! 7512: return (type); ! 7513: } ! 7514: } ! 7515: } ! 7516: ASC_DBG1(4, "asc_scan_method: type %d\n", type); ! 7517: return (type); ! 7518: } ! 7519: ! 7520: /* ! 7521: * Check for an AdvanSys PCI device in 'pciDevice'. ! 7522: * ! 7523: * Return PCI_DEVICE_FOUND if found, otherwise return PCI_DEVICE_NOT_FOUND. ! 7524: */ ! 7525: ASC_INITFUNC( ! 7526: STATIC int ! 7527: asc_pci_find_dev(PCI_DEVICE *pciDevice) ! 7528: ) ! 7529: { ! 7530: PCI_DATA pciData; ! 7531: ushort vendorid, deviceid; ! 7532: uchar classcode, subclass; ! 7533: uchar lslot; ! 7534: ! 7535: ASC_DBG(3, "asc_pci_find_dev: begin\n"); ! 7536: pciData.type = pciDevice->type; ! 7537: pciData.bus = pciDevice->busNumber; ! 7538: pciData.func = pciDevice->devFunc; ! 7539: lslot = pciDevice->startSlot; ! 7540: for (; lslot < pciDevice->endSlot; lslot++) { ! 7541: pciData.slot = lslot; ! 7542: pciData.offset = VENDORID_OFFSET; ! 7543: vendorid = asc_get_cfg_word(&pciData); ! 7544: ASC_DBG1(3, "asc_pci_find_dev: vendorid %x\n", vendorid); ! 7545: if (vendorid != 0xffff) { ! 7546: pciData.offset = DEVICEID_OFFSET; ! 7547: deviceid = asc_get_cfg_word(&pciData); ! 7548: ASC_DBG1(3, "asc_pci_find_dev: deviceid %x\n", deviceid); ! 7549: if ((vendorid == ASC_PCI_VENDORID) && ! 7550: ((deviceid == ASC_PCI_DEVICE_ID_1100) || ! 7551: (deviceid == ASC_PCI_DEVICE_ID_1200) || ! 7552: (deviceid == ASC_PCI_DEVICE_ID_1300) || ! 7553: (deviceid == ASC_PCI_DEVICE_ID_2300))) { ! 7554: pciDevice->slotFound = lslot; ! 7555: ASC_DBG(3, "asc_pci_find_dev: PCI_DEVICE_FOUND\n"); ! 7556: return PCI_DEVICE_FOUND; ! 7557: } else { ! 7558: pciData.offset = SUBCLASS_OFFSET; ! 7559: subclass = asc_get_cfg_byte(&pciData); ! 7560: pciData.offset = CLASSCODE_OFFSET; ! 7561: classcode = asc_get_cfg_byte(&pciData); ! 7562: if ((classcode & PCI_BASE_CLASS_BRIDGE_DEVICE) && ! 7563: (subclass & PCI_SUB_CLASS_PCI_TO_PCI_BRIDGE_CONTROLLER)) { ! 7564: pciDevice->bridge++; ! 7565: } ! 7566: ASC_DBG2(3, "asc_pci_find_dev: subclass %x, classcode %x\n", ! 7567: subclass, classcode); ! 7568: } ! 7569: } ! 7570: } ! 7571: return PCI_DEVICE_NOT_FOUND; ! 7572: } ! 7573: ! 7574: /* ! 7575: * Read PCI configuration data into 'pciConfig'. ! 7576: */ ! 7577: ASC_INITFUNC( ! 7578: STATIC void ! 7579: asc_get_pci_cfg(PCI_DEVICE *pciDevice, PCI_CONFIG_SPACE *pciConfig) ! 7580: ) ! 7581: { ! 7582: PCI_DATA pciData; ! 7583: uchar counter; ! 7584: uchar *localConfig; ! 7585: ! 7586: ASC_DBG1(4, "asc_get_pci_cfg: slotFound %d\n ", ! 7587: pciDevice->slotFound); ! 7588: ! 7589: pciData.type = pciDevice->type; ! 7590: pciData.bus = pciDevice->busNumber; ! 7591: pciData.slot = pciDevice->slotFound; ! 7592: pciData.func = pciDevice->devFunc; ! 7593: localConfig = (uchar *) pciConfig; ! 7594: ! 7595: for (counter = 0; counter < sizeof(PCI_CONFIG_SPACE); counter++) { ! 7596: pciData.offset = counter; ! 7597: *localConfig = asc_get_cfg_byte(&pciData); ! 7598: ASC_DBG1(4, "asc_get_pci_cfg: byte %x\n", *localConfig); ! 7599: localConfig++; ! 7600: } ! 7601: ASC_DBG1(4, "asc_get_pci_cfg: counter %d\n", counter); ! 7602: } ! 7603: ! 7604: /* ! 7605: * Read a word (16 bits) from the PCI configuration space. ! 7606: * ! 7607: * The configuration mechanism is checked for the correct access method. ! 7608: */ ! 7609: ASC_INITFUNC( ! 7610: STATIC ushort ! 7611: asc_get_cfg_word(PCI_DATA *pciData) ! 7612: ) ! 7613: { ! 7614: ushort tmp; ! 7615: ulong address; ! 7616: ulong lbus = pciData->bus; ! 7617: ulong lslot = pciData->slot; ! 7618: ulong lfunc = pciData->func; ! 7619: uchar t2CFA, t2CF8; ! 7620: ulong t1CF8, t1CFC; ! 7621: ! 7622: ASC_DBG4(4, "asc_get_cfg_word: type %d, bus %lu, slot %lu, func %lu\n", ! 7623: pciData->type, lbus, lslot, lfunc); ! 7624: ! 7625: /* ! 7626: * Check type of configuration mechanism. ! 7627: */ ! 7628: if (pciData->type == 2) { ! 7629: /* ! 7630: * Save registers to be restored later. ! 7631: */ ! 7632: t2CFA = inp(0xCFA); /* save PCI bus register */ ! 7633: t2CF8 = inp(0xCF8); /* save config space enable register */ ! 7634: ! 7635: /* ! 7636: * Write the bus and enable registers. ! 7637: */ ! 7638: /* set for type 1 cycle, if needed */ ! 7639: outp(0xCFA, pciData->bus); ! 7640: /* set the function number */ ! 7641: outp(0xCF8, 0x10 | (pciData->func << 1)) ; ! 7642: ! 7643: /* ! 7644: * Read the configuration space type 2 locations. ! 7645: */ ! 7646: tmp = (ushort) inpw(0xC000 | ((pciData->slot << 8) + pciData->offset)); ! 7647: ! 7648: outp(0xCFA, t2CFA); /* save PCI bus register */ ! 7649: outp(0xCF8, t2CF8); /* save config space enable register */ ! 7650: } else { ! 7651: /* ! 7652: * Type 1 or 3 configuration mechanism. ! 7653: * ! 7654: * Save the CONFIG_ADDRESS and CONFIG_DATA register values. ! 7655: */ ! 7656: t1CF8 = inpl(0xCF8); ! 7657: t1CFC = inpl(0xCFC); ! 7658: ! 7659: /* ! 7660: * enable <31>, bus = <23:16>, slot = <15:11>, ! 7661: * func = <10:8>, reg = <7:2> ! 7662: */ ! 7663: address = (ulong) ((lbus << 16) | (lslot << 11) | ! 7664: (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L); ! 7665: ! 7666: /* ! 7667: * Write out the address to CONFIG_ADDRESS. ! 7668: */ ! 7669: outpl(0xCF8, address); ! 7670: ! 7671: /* ! 7672: * Read in word from CONFIG_DATA. ! 7673: */ ! 7674: tmp = (ushort) ((inpl(0xCFC) >> ! 7675: ((pciData->offset & 2) * 8)) & 0xFFFF); ! 7676: ! 7677: /* ! 7678: * Restore registers. ! 7679: */ ! 7680: outpl(0xCF8, t1CF8); ! 7681: outpl(0xCFC, t1CFC); ! 7682: } ! 7683: ASC_DBG1(4, "asc_get_cfg_word: config data: %x\n", tmp); ! 7684: return tmp; ! 7685: } ! 7686: ! 7687: /* ! 7688: * Reads a byte from the PCI configuration space. ! 7689: * ! 7690: * The configuration mechanism is checked for the correct access method. ! 7691: */ ! 7692: ASC_INITFUNC( ! 7693: STATIC uchar ! 7694: asc_get_cfg_byte(PCI_DATA *pciData) ! 7695: ) ! 7696: { ! 7697: uchar tmp; ! 7698: ulong address; ! 7699: ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func; ! 7700: uchar t2CFA, t2CF8; ! 7701: ulong t1CF8, t1CFC; ! 7702: ! 7703: ASC_DBG1(4, "asc_get_cfg_byte: type: %d\n", pciData->type); ! 7704: ! 7705: /* ! 7706: * Check type of configuration mechanism. ! 7707: */ ! 7708: if (pciData->type == 2) { ! 7709: /* ! 7710: * Save registers to be restored later. ! 7711: */ ! 7712: t2CFA = inp(0xCFA); /* save PCI bus register */ ! 7713: t2CF8 = inp(0xCF8); /* save config space enable register */ ! 7714: ! 7715: /* ! 7716: * Write the bus and enable registers. ! 7717: */ ! 7718: /* set for type 1 cycle, if needed */ ! 7719: outp(0xCFA, pciData->bus); ! 7720: /* set the function number */ ! 7721: outp(0xCF8, 0x10 | (pciData->func << 1)); ! 7722: ! 7723: /* ! 7724: * Read configuration space type 2 locations. ! 7725: */ ! 7726: tmp = inp(0xC000 | ((pciData->slot << 8) + pciData->offset)); ! 7727: ! 7728: /* ! 7729: * Restore registers. ! 7730: */ ! 7731: outp(0xCF8, t2CF8); /* restore the enable register */ ! 7732: outp(0xCFA, t2CFA); /* restore PCI bus register */ ! 7733: } else { ! 7734: /* ! 7735: * Type 1 or 3 configuration mechanism. ! 7736: * ! 7737: * Save CONFIG_ADDRESS and CONFIG_DATA register values. ! 7738: */ ! 7739: t1CF8 = inpl(0xCF8); ! 7740: t1CFC = inpl(0xCFC); ! 7741: ! 7742: /* ! 7743: * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>, ! 7744: * reg = <7:2> ! 7745: */ ! 7746: address = (ulong) ((lbus << 16) | (lslot << 11) | ! 7747: (lfunc << 8) | (pciData->offset & 0xFC) | 0x80000000L); ! 7748: ! 7749: /* ! 7750: * Write out address to CONFIG_ADDRESS. ! 7751: */ ! 7752: outpl(0xCF8, address); ! 7753: ! 7754: /* ! 7755: * Read in word from CONFIG_DATA. ! 7756: */ ! 7757: tmp = (uchar) ((inpl(0xCFC) >> ((pciData->offset & 3) * 8)) & 0xFF); ! 7758: ! 7759: /* ! 7760: * Restore registers. ! 7761: */ ! 7762: outpl(0xCF8, t1CF8); ! 7763: outpl(0xCFC, t1CFC); ! 7764: } ! 7765: ASC_DBG1(4, "asc_get_cfg_byte: config data: %x\n", tmp); ! 7766: return tmp; ! 7767: } ! 7768: ! 7769: /* ! 7770: * Write a byte to the PCI configuration space. ! 7771: */ ! 7772: ASC_INITFUNC( ! 7773: STATIC void ! 7774: asc_put_cfg_byte(PCI_DATA *pciData, uchar byte_data) ! 7775: ) ! 7776: { ! 7777: ulong tmpl; ! 7778: ulong address; ! 7779: ulong lbus = pciData->bus, lslot = pciData->slot, lfunc = pciData->func; ! 7780: uchar t2CFA, t2CF8; ! 7781: ulong t1CF8, t1CFC; ! 7782: ! 7783: ASC_DBG2(4, "asc_put_cfg_byte: type: %d, byte_data %x\n", ! 7784: pciData->type, byte_data); ! 7785: ! 7786: /* ! 7787: * Check type of configuration mechanism. ! 7788: */ ! 7789: if (pciData->type == 2) { ! 7790: ! 7791: /* ! 7792: * Save registers to be restored later. ! 7793: */ ! 7794: t2CFA = inp(0xCFA); /* save PCI bus register */ ! 7795: t2CF8 = inp(0xCF8); /* save config space enable register */ ! 7796: ! 7797: /* ! 7798: * Write bus and enable registers. ! 7799: */ ! 7800: outp(0xCFA, pciData->bus); ! 7801: ! 7802: /* ! 7803: * Set the function number. ! 7804: */ ! 7805: outp(0xCF8, 0x10 | (pciData->func << 1)); ! 7806: ! 7807: /* ! 7808: * Write the configuration space type 2 locations. ! 7809: */ ! 7810: outp(0xC000 | ((pciData->slot << 8) + pciData->offset), byte_data); ! 7811: ! 7812: /* ! 7813: * Restore registers. ! 7814: */ ! 7815: outp(0xCF8, t2CF8); /* restore the enable register */ ! 7816: outp(0xCFA, t2CFA); /* restore PCI bus register */ ! 7817: } else { ! 7818: ! 7819: /* ! 7820: * Type 1 or 3 configuration mechanism. ! 7821: * ! 7822: * Save the CONFIG_ADDRESS and CONFIG_DATA register values. ! 7823: */ ! 7824: t1CF8 = inpl(0xCF8); ! 7825: t1CFC = inpl(0xCFC); ! 7826: ! 7827: /* ! 7828: * enable <31>, bus = <23:16>, slot = <15:11>, func = <10:8>, ! 7829: * reg = <7:2> ! 7830: */ ! 7831: address = (ulong) ((lbus << 16) | (lslot << 11) | (lfunc << 8) | ! 7832: (pciData->offset & 0xFC) | 0x80000000L); ! 7833: /* ! 7834: * Write out address to CONFIG_ADDRESS. ! 7835: */ ! 7836: outpl(0xCF8, address); ! 7837: ! 7838: /* ! 7839: * Write double word to CONFIG_DATA preserving the bytes ! 7840: * in the double not written. ! 7841: */ ! 7842: tmpl = inpl(0xCFC) & ~(0xFF << ((pciData->offset & 3) * 8)); ! 7843: outpl(0xCFC, tmpl | (byte_data << ((pciData->offset & 3) * 8))); ! 7844: ! 7845: /* ! 7846: * Restore registers. ! 7847: */ ! 7848: outpl(0xCF8, t1CF8); ! 7849: outpl(0xCFC, t1CFC); ! 7850: } ! 7851: ASC_DBG(4, "asc_put_cfg_byte: end\n"); ! 7852: } ! 7853: #endif /* ASC_CONFIG_PCI */ ! 7854: #endif /* version < v2.1.93 */ ! 7855: ! 7856: /* ! 7857: * Add a 'REQP' to the end of specified queue. Set 'tidmask' ! 7858: * to indicate a command is queued for the device. ! 7859: * ! 7860: * 'flag' may be either ASC_FRONT or ASC_BACK. ! 7861: * ! 7862: * 'REQPNEXT(reqp)' returns reqp's next pointer. ! 7863: */ ! 7864: STATIC void ! 7865: asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag) ! 7866: { ! 7867: int tid; ! 7868: ! 7869: ASC_DBG3(3, "asc_enqueue: ascq %x, reqp %x, flag %d\n", ! 7870: (unsigned) ascq, (unsigned) reqp, flag); ! 7871: ASC_ASSERT(interrupts_enabled() == ASC_FALSE); ! 7872: ASC_ASSERT(reqp != NULL); ! 7873: ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK); ! 7874: tid = REQPTID(reqp); ! 7875: ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); ! 7876: if (flag == ASC_FRONT) { ! 7877: REQPNEXT(reqp) = ascq->q_first[tid]; ! 7878: ascq->q_first[tid] = reqp; ! 7879: /* If the queue was empty, set the last pointer. */ ! 7880: if (ascq->q_last[tid] == NULL) { ! 7881: ascq->q_last[tid] = reqp; ! 7882: } ! 7883: } else { /* ASC_BACK */ ! 7884: if (ascq->q_last[tid] != NULL) { ! 7885: REQPNEXT(ascq->q_last[tid]) = reqp; ! 7886: } ! 7887: ascq->q_last[tid] = reqp; ! 7888: REQPNEXT(reqp) = NULL; ! 7889: /* If the queue was empty, set the first pointer. */ ! 7890: if (ascq->q_first[tid] == NULL) { ! 7891: ascq->q_first[tid] = reqp; ! 7892: } ! 7893: } ! 7894: /* The queue has at least one entry, set its bit. */ ! 7895: ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid); ! 7896: #ifdef ADVANSYS_STATS ! 7897: /* Maintain request queue statistics. */ ! 7898: ascq->q_tot_cnt[tid]++; ! 7899: ascq->q_cur_cnt[tid]++; ! 7900: if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) { ! 7901: ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid]; ! 7902: ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n", ! 7903: tid, ascq->q_max_cnt[tid]); ! 7904: } ! 7905: REQPTIME(reqp) = REQTIMESTAMP(); ! 7906: #endif /* ADVANSYS_STATS */ ! 7907: ASC_DBG1(3, "asc_enqueue: reqp %x\n", (unsigned) reqp); ! 7908: return; ! 7909: } ! 7910: ! 7911: /* ! 7912: * Return first queued 'REQP' on the specified queue for ! 7913: * the specified target device. Clear the 'tidmask' bit for ! 7914: * the device if no more commands are left queued for it. ! 7915: * ! 7916: * 'REQPNEXT(reqp)' returns reqp's next pointer. ! 7917: */ ! 7918: STATIC REQP ! 7919: asc_dequeue(asc_queue_t *ascq, int tid) ! 7920: { ! 7921: REQP reqp; ! 7922: ! 7923: ASC_DBG2(3, "asc_dequeue: ascq %x, tid %d\n", (unsigned) ascq, tid); ! 7924: ASC_ASSERT(interrupts_enabled() == ASC_FALSE); ! 7925: ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); ! 7926: if ((reqp = ascq->q_first[tid]) != NULL) { ! 7927: ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)); ! 7928: ascq->q_first[tid] = REQPNEXT(reqp); ! 7929: /* If the queue is empty, clear its bit and the last pointer. */ ! 7930: if (ascq->q_first[tid] == NULL) { ! 7931: ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); ! 7932: ASC_ASSERT(ascq->q_last[tid] == reqp); ! 7933: ascq->q_last[tid] = NULL; ! 7934: } ! 7935: #ifdef ADVANSYS_STATS ! 7936: /* Maintain request queue statistics. */ ! 7937: ascq->q_cur_cnt[tid]--; ! 7938: ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); ! 7939: REQTIMESTAT("asc_dequeue", ascq, reqp, tid); ! 7940: #endif /* ADVANSYS_STATS */ ! 7941: } ! 7942: ASC_DBG1(3, "asc_dequeue: reqp %x\n", (unsigned) reqp); ! 7943: return reqp; ! 7944: } ! 7945: ! 7946: /* ! 7947: * Return a pointer to a singly linked list of all the requests queued ! 7948: * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'. ! 7949: * ! 7950: * If 'lastpp' is not NULL, '*lastpp' will be set to point to the ! 7951: * the last request returned in the singly linked list. ! 7952: * ! 7953: * 'tid' should either be a valid target id or if it is ASC_TID_ALL, ! 7954: * then all queued requests are concatenated into one list and ! 7955: * returned. ! 7956: * ! 7957: * Note: If 'lastpp' is used to append a new list to the end of ! 7958: * an old list, only change the old list last pointer if '*lastpp' ! 7959: * (or the function return value) is not NULL, i.e. use a temporary ! 7960: * variable for 'lastpp' and check its value after the function return ! 7961: * before assigning it to the list last pointer. ! 7962: * ! 7963: * Unfortunately collecting queuing time statistics adds overhead to ! 7964: * the function that isn't inherent to the function's algorithm. ! 7965: */ ! 7966: STATIC REQP ! 7967: asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid) ! 7968: { ! 7969: REQP firstp, lastp; ! 7970: int i; ! 7971: ! 7972: ASC_DBG2(3, "asc_dequeue_list: ascq %x, tid %d\n", (unsigned) ascq, tid); ! 7973: ASC_ASSERT(interrupts_enabled() == ASC_FALSE); ! 7974: ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID)); ! 7975: ! 7976: /* ! 7977: * If 'tid' is not ASC_TID_ALL, return requests only for ! 7978: * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all ! 7979: * requests for all tids. ! 7980: */ ! 7981: if (tid != ASC_TID_ALL) { ! 7982: /* Return all requests for the specified 'tid'. */ ! 7983: if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) { ! 7984: /* List is empty; Set first and last return pointers to NULL. */ ! 7985: firstp = lastp = NULL; ! 7986: } else { ! 7987: firstp = ascq->q_first[tid]; ! 7988: lastp = ascq->q_last[tid]; ! 7989: ascq->q_first[tid] = ascq->q_last[tid] = NULL; ! 7990: ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); ! 7991: #ifdef ADVANSYS_STATS ! 7992: { ! 7993: REQP reqp; ! 7994: ascq->q_cur_cnt[tid] = 0; ! 7995: for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) { ! 7996: REQTIMESTAT("asc_dequeue_list", ascq, reqp, tid); ! 7997: } ! 7998: } ! 7999: #endif /* ADVANSYS_STATS */ ! 8000: } ! 8001: } else { ! 8002: /* Return all requests for all tids. */ ! 8003: firstp = lastp = NULL; ! 8004: for (i = 0; i <= ADV_MAX_TID; i++) { ! 8005: if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) { ! 8006: if (firstp == NULL) { ! 8007: firstp = ascq->q_first[i]; ! 8008: lastp = ascq->q_last[i]; ! 8009: } else { ! 8010: ASC_ASSERT(lastp != NULL); ! 8011: REQPNEXT(lastp) = ascq->q_first[i]; ! 8012: lastp = ascq->q_last[i]; ! 8013: } ! 8014: ascq->q_first[i] = ascq->q_last[i] = NULL; ! 8015: ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i); ! 8016: #ifdef ADVANSYS_STATS ! 8017: ascq->q_cur_cnt[i] = 0; ! 8018: #endif /* ADVANSYS_STATS */ ! 8019: } ! 8020: } ! 8021: #ifdef ADVANSYS_STATS ! 8022: { ! 8023: REQP reqp; ! 8024: for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) { ! 8025: REQTIMESTAT("asc_dequeue_list", ascq, reqp, reqp->target); ! 8026: } ! 8027: } ! 8028: #endif /* ADVANSYS_STATS */ ! 8029: } ! 8030: if (lastpp) { ! 8031: *lastpp = lastp; ! 8032: } ! 8033: ASC_DBG1(3, "asc_dequeue_list: firstp %x\n", (unsigned) firstp); ! 8034: return firstp; ! 8035: } ! 8036: ! 8037: /* ! 8038: * Remove the specified 'REQP' from the specified queue for ! 8039: * the specified target device. Clear the 'tidmask' bit for the ! 8040: * device if no more commands are left queued for it. ! 8041: * ! 8042: * 'REQPNEXT(reqp)' returns reqp's the next pointer. ! 8043: * ! 8044: * Return ASC_TRUE if the command was found and removed, ! 8045: * otherwise return ASC_FALSE. ! 8046: */ ! 8047: STATIC int ! 8048: asc_rmqueue(asc_queue_t *ascq, REQP reqp) ! 8049: { ! 8050: REQP currp, prevp; ! 8051: int tid; ! 8052: int ret = ASC_FALSE; ! 8053: ! 8054: ASC_DBG2(3, "asc_rmqueue: ascq %x, reqp %x\n", ! 8055: (unsigned) ascq, (unsigned) reqp); ! 8056: ASC_ASSERT(interrupts_enabled() == ASC_FALSE); ! 8057: ASC_ASSERT(reqp != NULL); ! 8058: ! 8059: tid = REQPTID(reqp); ! 8060: ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); ! 8061: ! 8062: /* ! 8063: * Handle the common case of 'reqp' being the first ! 8064: * entry on the queue. ! 8065: */ ! 8066: if (reqp == ascq->q_first[tid]) { ! 8067: ret = ASC_TRUE; ! 8068: ascq->q_first[tid] = REQPNEXT(reqp); ! 8069: /* If the queue is now empty, clear its bit and the last pointer. */ ! 8070: if (ascq->q_first[tid] == NULL) { ! 8071: ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); ! 8072: ASC_ASSERT(ascq->q_last[tid] == reqp); ! 8073: ascq->q_last[tid] = NULL; ! 8074: } ! 8075: } else if (ascq->q_first[tid] != NULL) { ! 8076: ASC_ASSERT(ascq->q_last[tid] != NULL); ! 8077: /* ! 8078: * Because the case of 'reqp' being the first entry has been ! 8079: * handled above and it is known the queue is not empty, if ! 8080: * 'reqp' is found on the queue it is guaranteed the queue will ! 8081: * not become empty and that 'q_first[tid]' will not be changed. ! 8082: * ! 8083: * Set 'prevp' to the first entry, 'currp' to the second entry, ! 8084: * and search for 'reqp'. ! 8085: */ ! 8086: for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp); ! 8087: currp; prevp = currp, currp = REQPNEXT(currp)) { ! 8088: if (currp == reqp) { ! 8089: ret = ASC_TRUE; ! 8090: REQPNEXT(prevp) = REQPNEXT(currp); ! 8091: REQPNEXT(reqp) = NULL; ! 8092: if (ascq->q_last[tid] == reqp) { ! 8093: ascq->q_last[tid] = prevp; ! 8094: } ! 8095: break; ! 8096: } ! 8097: } ! 8098: } ! 8099: #ifdef ADVANSYS_STATS ! 8100: /* Maintain request queue statistics. */ ! 8101: if (ret == ASC_TRUE) { ! 8102: ascq->q_cur_cnt[tid]--; ! 8103: REQTIMESTAT("asc_rmqueue", ascq, reqp, tid); ! 8104: } ! 8105: ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); ! 8106: #endif /* ADVANSYS_STATS */ ! 8107: ASC_DBG2(3, "asc_rmqueue: reqp %x, ret %d\n", (unsigned) reqp, ret); ! 8108: return ret; ! 8109: } ! 8110: ! 8111: /* ! 8112: * If the specified 'REQP' is queued on the specified queue for ! 8113: * the specified target device, return ASC_TRUE. ! 8114: */ ! 8115: STATIC int ! 8116: asc_isqueued(asc_queue_t *ascq, REQP reqp) ! 8117: { ! 8118: REQP treqp; ! 8119: int tid; ! 8120: int ret = ASC_FALSE; ! 8121: ! 8122: ASC_DBG2(3, "asc_isqueued: ascq %x, reqp %x\n", ! 8123: (unsigned) ascq, (unsigned) reqp); ! 8124: ASC_ASSERT(interrupts_enabled() == ASC_FALSE); ! 8125: ASC_ASSERT(reqp != NULL); ! 8126: ! 8127: tid = REQPTID(reqp); ! 8128: ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); ! 8129: ! 8130: for (treqp = ascq->q_first[tid]; treqp; treqp = REQPNEXT(treqp)) { ! 8131: ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)); ! 8132: if (treqp == reqp) { ! 8133: ret = ASC_TRUE; ! 8134: break; ! 8135: } ! 8136: } ! 8137: ASC_DBG1(3, "asc_isqueued: ret %x\n", ret); ! 8138: return ret; ! 8139: } ! 8140: ! 8141: /* ! 8142: * Execute as many queued requests as possible for the specified queue. ! 8143: * ! 8144: * Calls asc_execute_scsi_cmnd() to execute a REQP/Scsi_Cmnd. ! 8145: */ ! 8146: STATIC void ! 8147: asc_execute_queue(asc_queue_t *ascq) ! 8148: { ! 8149: ADV_SCSI_BIT_ID_TYPE scan_tidmask; ! 8150: REQP reqp; ! 8151: int i; ! 8152: ! 8153: ASC_DBG1(1, "asc_execute_queue: ascq %x\n", (unsigned) ascq); ! 8154: ASC_ASSERT(interrupts_enabled() == ASC_FALSE); ! 8155: /* ! 8156: * Execute queued commands for devices attached to ! 8157: * the current board in round-robin fashion. ! 8158: */ ! 8159: scan_tidmask = ascq->q_tidmask; ! 8160: do { ! 8161: for (i = 0; i <= ADV_MAX_TID; i++) { ! 8162: if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) { ! 8163: if ((reqp = asc_dequeue(ascq, i)) == NULL) { ! 8164: scan_tidmask &= ~ADV_TID_TO_TIDMASK(i); ! 8165: } else if (asc_execute_scsi_cmnd((Scsi_Cmnd *) reqp) ! 8166: == ASC_BUSY) { ! 8167: scan_tidmask &= ~ADV_TID_TO_TIDMASK(i); ! 8168: /* Put the request back at front of the list. */ ! 8169: asc_enqueue(ascq, reqp, ASC_FRONT); ! 8170: } ! 8171: } ! 8172: } ! 8173: } while (scan_tidmask); ! 8174: return; ! 8175: } ! 8176: ! 8177: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0) ! 8178: /* ! 8179: * asc_prt_board_devices() ! 8180: * ! 8181: * Print driver information for devices attached to the board. ! 8182: * ! 8183: * Note: no single line should be greater than ASC_PRTLINE_SIZE, ! 8184: * cf. asc_prt_line(). ! 8185: * ! 8186: * Return the number of characters copied into 'cp'. No more than ! 8187: * 'cplen' characters will be copied to 'cp'. ! 8188: */ ! 8189: STATIC int ! 8190: asc_prt_board_devices(struct Scsi_Host *shp, char *cp, int cplen) ! 8191: { ! 8192: asc_board_t *boardp; ! 8193: int leftlen; ! 8194: int totlen; ! 8195: int len; ! 8196: int chip_scsi_id; ! 8197: int i; ! 8198: ! 8199: boardp = ASC_BOARDP(shp); ! 8200: leftlen = cplen; ! 8201: totlen = len = 0; ! 8202: ! 8203: len = asc_prt_line(cp, leftlen, ! 8204: "\nDevice Information for AdvanSys SCSI Host %d:\n", shp->host_no); ! 8205: ASC_PRT_NEXT(); ! 8206: ! 8207: if (ASC_NARROW_BOARD(boardp)) { ! 8208: chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; ! 8209: } else { ! 8210: chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; ! 8211: } ! 8212: ! 8213: len = asc_prt_line(cp, leftlen, "Target IDs Detected:"); ! 8214: ASC_PRT_NEXT(); ! 8215: for (i = 0; i <= ADV_MAX_TID; i++) { ! 8216: if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) { ! 8217: len = asc_prt_line(cp, leftlen, " %X,", i); ! 8218: ASC_PRT_NEXT(); ! 8219: } ! 8220: } ! 8221: len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id); ! 8222: ASC_PRT_NEXT(); ! 8223: ! 8224: return totlen; ! 8225: } ! 8226: ! 8227: /* ! 8228: * Display Wide Board BIOS Information. ! 8229: */ ! 8230: STATIC int ! 8231: asc_prt_adv_bios(struct Scsi_Host *shp, char *cp, int cplen) ! 8232: { ! 8233: asc_board_t *boardp; ! 8234: int leftlen; ! 8235: int totlen; ! 8236: int len; ! 8237: int upgrade = ASC_FALSE; ! 8238: ushort major, minor, letter; ! 8239: ! 8240: boardp = ASC_BOARDP(shp); ! 8241: leftlen = cplen; ! 8242: totlen = len = 0; ! 8243: ! 8244: len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: "); ! 8245: ASC_PRT_NEXT(); ! 8246: ! 8247: /* ! 8248: * If the BIOS saved a valid signature, then fill in ! 8249: * the BIOS code segment base address. ! 8250: */ ! 8251: if (boardp->bios_signature != 0x55AA) { ! 8252: len = asc_prt_line(cp, leftlen, "Pre-3.1\n"); ! 8253: ASC_PRT_NEXT(); ! 8254: upgrade = ASC_TRUE; ! 8255: } else { ! 8256: major = (boardp->bios_version >> 12) & 0xF; ! 8257: minor = (boardp->bios_version >> 8) & 0xF; ! 8258: letter = (boardp->bios_version & 0xFF); ! 8259: ! 8260: len = asc_prt_line(cp, leftlen, "%d.%d%c\n", ! 8261: major, minor, letter >= 26 ? '?' : letter + 'A'); ! 8262: ASC_PRT_NEXT(); ! 8263: ! 8264: /* Current available ROM BIOS release is 3.1C. */ ! 8265: if (major < 3 || (major <= 3 && minor < 1) || ! 8266: (major <= 3 && minor <= 1 && letter < ('C'- 'A'))) { ! 8267: upgrade = ASC_TRUE; ! 8268: } ! 8269: } ! 8270: if (upgrade == ASC_TRUE) { ! 8271: len = asc_prt_line(cp, leftlen, ! 8272: "Newer version of ROM BIOS available: ftp://ftp.advansys.com/pub\n"); ! 8273: ASC_PRT_NEXT(); ! 8274: } ! 8275: ! 8276: return totlen; ! 8277: } ! 8278: ! 8279: /* ! 8280: * Add serial number to information bar if signature AAh ! 8281: * is found in at bit 15-9 (7 bits) of word 1. ! 8282: * ! 8283: * Serial Number consists fo 12 alpha-numeric digits. ! 8284: * ! 8285: * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits) ! 8286: * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits) ! 8287: * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits) ! 8288: * 5 - Product revision (A-J) Word0: " " ! 8289: * ! 8290: * Signature Word1: 15-9 (7 bits) ! 8291: * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit) ! 8292: * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits) ! 8293: * ! 8294: * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits) ! 8295: * ! 8296: * Note 1: Only production cards will have a serial number. ! 8297: * ! 8298: * Note 2: Signature is most significant 7 bits (0xFE). ! 8299: * ! 8300: * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE. ! 8301: */ ! 8302: STATIC int ! 8303: asc_get_eeprom_string(ushort *serialnum, uchar *cp) ! 8304: { ! 8305: ushort w, num; ! 8306: ! 8307: if ((serialnum[1] & 0xFE00) != ((ushort) 0xAA << 8)) { ! 8308: return ASC_FALSE; ! 8309: } else { ! 8310: /* ! 8311: * First word - 6 digits. ! 8312: */ ! 8313: w = serialnum[0]; ! 8314: ! 8315: /* Product type - 1st digit. */ ! 8316: if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') { ! 8317: /* Product type is P=Prototype */ ! 8318: *cp += 0x8; ! 8319: } ! 8320: cp++; ! 8321: ! 8322: /* Manufacturing location - 2nd digit. */ ! 8323: *cp++ = 'A' + ((w & 0x1C00) >> 10); ! 8324: ! 8325: /* Product ID - 3rd, 4th digits. */ ! 8326: num = w & 0x3FF; ! 8327: *cp++ = '0' + (num / 100); ! 8328: num %= 100; ! 8329: *cp++ = '0' + (num / 10); ! 8330: ! 8331: /* Product revision - 5th digit. */ ! 8332: *cp++ = 'A' + (num % 10); ! 8333: ! 8334: /* ! 8335: * Second word ! 8336: */ ! 8337: w = serialnum[1]; ! 8338: ! 8339: /* ! 8340: * Year - 6th digit. ! 8341: * ! 8342: * If bit 15 of third word is set, then the ! 8343: * last digit of the year is greater than 7. ! 8344: */ ! 8345: if (serialnum[2] & 0x8000) { ! 8346: *cp++ = '8' + ((w & 0x1C0) >> 6); ! 8347: } else { ! 8348: *cp++ = '0' + ((w & 0x1C0) >> 6); ! 8349: } ! 8350: ! 8351: /* Week of year - 7th, 8th digits. */ ! 8352: num = w & 0x003F; ! 8353: *cp++ = '0' + num / 10; ! 8354: num %= 10; ! 8355: *cp++ = '0' + num; ! 8356: ! 8357: /* ! 8358: * Third word ! 8359: */ ! 8360: w = serialnum[2] & 0x7FFF; ! 8361: ! 8362: /* Serial number - 9th digit. */ ! 8363: *cp++ = 'A' + (w / 1000); ! 8364: ! 8365: /* 10th, 11th, 12th digits. */ ! 8366: num = w % 1000; ! 8367: *cp++ = '0' + num / 100; ! 8368: num %= 100; ! 8369: *cp++ = '0' + num / 10; ! 8370: num %= 10; ! 8371: *cp++ = '0' + num; ! 8372: ! 8373: *cp = '\0'; /* Null Terminate the string. */ ! 8374: return ASC_TRUE; ! 8375: } ! 8376: } ! 8377: ! 8378: /* ! 8379: * asc_prt_asc_board_eeprom() ! 8380: * ! 8381: * Print board EEPROM configuration. ! 8382: * ! 8383: * Note: no single line should be greater than ASC_PRTLINE_SIZE, ! 8384: * cf. asc_prt_line(). ! 8385: * ! 8386: * Return the number of characters copied into 'cp'. No more than ! 8387: * 'cplen' characters will be copied to 'cp'. ! 8388: */ ! 8389: STATIC int ! 8390: asc_prt_asc_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen) ! 8391: { ! 8392: asc_board_t *boardp; ! 8393: ASC_DVC_VAR *asc_dvc_varp; ! 8394: int leftlen; ! 8395: int totlen; ! 8396: int len; ! 8397: ASCEEP_CONFIG *ep; ! 8398: int i; ! 8399: int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 }; ! 8400: uchar serialstr[13]; ! 8401: ! 8402: boardp = ASC_BOARDP(shp); ! 8403: asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; ! 8404: ep = &boardp->eep_config.asc_eep; ! 8405: ! 8406: leftlen = cplen; ! 8407: totlen = len = 0; ! 8408: ! 8409: len = asc_prt_line(cp, leftlen, ! 8410: "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no); ! 8411: ASC_PRT_NEXT(); ! 8412: ! 8413: if (asc_get_eeprom_string((ushort *) &ep->adapter_info[0], serialstr) == ! 8414: ASC_TRUE) { ! 8415: len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr); ! 8416: ASC_PRT_NEXT(); ! 8417: } else { ! 8418: if (ep->adapter_info[5] == 0xBB) { ! 8419: len = asc_prt_line(cp, leftlen, ! 8420: " Default Settings Used for EEPROM-less Adapter.\n"); ! 8421: ASC_PRT_NEXT(); ! 8422: } else { ! 8423: len = asc_prt_line(cp, leftlen, ! 8424: " Serial Number Signature Not Present.\n"); ! 8425: ASC_PRT_NEXT(); ! 8426: } ! 8427: } ! 8428: ! 8429: len = asc_prt_line(cp, leftlen, ! 8430: " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", ! 8431: ep->chip_scsi_id, ep->max_total_qng, ep->max_tag_qng); ! 8432: ASC_PRT_NEXT(); ! 8433: ! 8434: len = asc_prt_line(cp, leftlen, ! 8435: " cntl %x, no_scam %x\n", ! 8436: ep->cntl, ep->no_scam); ! 8437: ASC_PRT_NEXT(); ! 8438: ! 8439: len = asc_prt_line(cp, leftlen, ! 8440: " Target ID: "); ! 8441: ASC_PRT_NEXT(); ! 8442: for (i = 0; i <= ASC_MAX_TID; i++) { ! 8443: len = asc_prt_line(cp, leftlen, " %d", i); ! 8444: ASC_PRT_NEXT(); ! 8445: } ! 8446: len = asc_prt_line(cp, leftlen, "\n"); ! 8447: ASC_PRT_NEXT(); ! 8448: ! 8449: len = asc_prt_line(cp, leftlen, ! 8450: " Disconnects: "); ! 8451: ASC_PRT_NEXT(); ! 8452: for (i = 0; i <= ASC_MAX_TID; i++) { ! 8453: len = asc_prt_line(cp, leftlen, " %c", ! 8454: (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 8455: ASC_PRT_NEXT(); ! 8456: } ! 8457: len = asc_prt_line(cp, leftlen, "\n"); ! 8458: ASC_PRT_NEXT(); ! 8459: ! 8460: len = asc_prt_line(cp, leftlen, ! 8461: " Command Queuing: "); ! 8462: ASC_PRT_NEXT(); ! 8463: for (i = 0; i <= ASC_MAX_TID; i++) { ! 8464: len = asc_prt_line(cp, leftlen, " %c", ! 8465: (ep->use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 8466: ASC_PRT_NEXT(); ! 8467: } ! 8468: len = asc_prt_line(cp, leftlen, "\n"); ! 8469: ASC_PRT_NEXT(); ! 8470: ! 8471: len = asc_prt_line(cp, leftlen, ! 8472: " Start Motor: "); ! 8473: ASC_PRT_NEXT(); ! 8474: for (i = 0; i <= ASC_MAX_TID; i++) { ! 8475: len = asc_prt_line(cp, leftlen, " %c", ! 8476: (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 8477: ASC_PRT_NEXT(); ! 8478: } ! 8479: len = asc_prt_line(cp, leftlen, "\n"); ! 8480: ASC_PRT_NEXT(); ! 8481: ! 8482: len = asc_prt_line(cp, leftlen, ! 8483: " Synchronous Transfer:"); ! 8484: ASC_PRT_NEXT(); ! 8485: for (i = 0; i <= ASC_MAX_TID; i++) { ! 8486: len = asc_prt_line(cp, leftlen, " %c", ! 8487: (ep->init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 8488: ASC_PRT_NEXT(); ! 8489: } ! 8490: len = asc_prt_line(cp, leftlen, "\n"); ! 8491: ASC_PRT_NEXT(); ! 8492: ! 8493: if (asc_dvc_varp->bus_type & ASC_IS_ISA) { ! 8494: len = asc_prt_line(cp, leftlen, ! 8495: " Host ISA DMA speed: %d MB/S\n", ! 8496: isa_dma_speed[ep->isa_dma_speed]); ! 8497: ASC_PRT_NEXT(); ! 8498: } ! 8499: ! 8500: return totlen; ! 8501: } ! 8502: ! 8503: /* ! 8504: * asc_prt_adv_board_eeprom() ! 8505: * ! 8506: * Print board EEPROM configuration. ! 8507: * ! 8508: * Note: no single line should be greater than ASC_PRTLINE_SIZE, ! 8509: * cf. asc_prt_line(). ! 8510: * ! 8511: * Return the number of characters copied into 'cp'. No more than ! 8512: * 'cplen' characters will be copied to 'cp'. ! 8513: */ ! 8514: STATIC int ! 8515: asc_prt_adv_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen) ! 8516: { ! 8517: asc_board_t *boardp; ! 8518: ADV_DVC_VAR *adv_dvc_varp; ! 8519: int leftlen; ! 8520: int totlen; ! 8521: int len; ! 8522: int i; ! 8523: char *termstr; ! 8524: uchar serialstr[13]; ! 8525: ADVEEP_CONFIG *ep; ! 8526: ! 8527: boardp = ASC_BOARDP(shp); ! 8528: adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; ! 8529: ep = &boardp->eep_config.adv_eep; ! 8530: ! 8531: leftlen = cplen; ! 8532: totlen = len = 0; ! 8533: ! 8534: len = asc_prt_line(cp, leftlen, ! 8535: "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", shp->host_no); ! 8536: ASC_PRT_NEXT(); ! 8537: ! 8538: if (asc_get_eeprom_string(&ep->serial_number_word1, serialstr) == ! 8539: ASC_TRUE) { ! 8540: len = asc_prt_line(cp, leftlen, " Serial Number: %s\n", serialstr); ! 8541: ASC_PRT_NEXT(); ! 8542: } else { ! 8543: len = asc_prt_line(cp, leftlen, ! 8544: " Serial Number Signature Not Present.\n"); ! 8545: ASC_PRT_NEXT(); ! 8546: } ! 8547: ! 8548: len = asc_prt_line(cp, leftlen, ! 8549: " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", ! 8550: ep->adapter_scsi_id, ep->max_host_qng, ep->max_dvc_qng); ! 8551: ASC_PRT_NEXT(); ! 8552: ! 8553: switch (ep->termination) { ! 8554: case 1: ! 8555: termstr = "Low Off/High Off"; ! 8556: break; ! 8557: case 2: ! 8558: termstr = "Low Off/High On"; ! 8559: break; ! 8560: case 3: ! 8561: termstr = "Low On/High On"; ! 8562: break; ! 8563: default: ! 8564: case 0: ! 8565: termstr = "Automatic"; ! 8566: break; ! 8567: } ! 8568: ! 8569: len = asc_prt_line(cp, leftlen, ! 8570: " termination: %u (%s), bios_ctrl: %x\n", ! 8571: ep->termination, termstr, ep->bios_ctrl); ! 8572: ASC_PRT_NEXT(); ! 8573: ! 8574: len = asc_prt_line(cp, leftlen, ! 8575: " Target ID: "); ! 8576: ASC_PRT_NEXT(); ! 8577: for (i = 0; i <= ADV_MAX_TID; i++) { ! 8578: len = asc_prt_line(cp, leftlen, " %X", i); ! 8579: ASC_PRT_NEXT(); ! 8580: } ! 8581: len = asc_prt_line(cp, leftlen, "\n"); ! 8582: ASC_PRT_NEXT(); ! 8583: ! 8584: len = asc_prt_line(cp, leftlen, ! 8585: " Disconnects: "); ! 8586: ASC_PRT_NEXT(); ! 8587: for (i = 0; i <= ADV_MAX_TID; i++) { ! 8588: len = asc_prt_line(cp, leftlen, " %c", ! 8589: (ep->disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 8590: ASC_PRT_NEXT(); ! 8591: } ! 8592: len = asc_prt_line(cp, leftlen, "\n"); ! 8593: ASC_PRT_NEXT(); ! 8594: ! 8595: len = asc_prt_line(cp, leftlen, ! 8596: " Command Queuing: "); ! 8597: ASC_PRT_NEXT(); ! 8598: for (i = 0; i <= ADV_MAX_TID; i++) { ! 8599: len = asc_prt_line(cp, leftlen, " %c", ! 8600: (ep->tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 8601: ASC_PRT_NEXT(); ! 8602: } ! 8603: len = asc_prt_line(cp, leftlen, "\n"); ! 8604: ASC_PRT_NEXT(); ! 8605: ! 8606: len = asc_prt_line(cp, leftlen, ! 8607: " Start Motor: "); ! 8608: ASC_PRT_NEXT(); ! 8609: for (i = 0; i <= ADV_MAX_TID; i++) { ! 8610: len = asc_prt_line(cp, leftlen, " %c", ! 8611: (ep->start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 8612: ASC_PRT_NEXT(); ! 8613: } ! 8614: len = asc_prt_line(cp, leftlen, "\n"); ! 8615: ASC_PRT_NEXT(); ! 8616: ! 8617: len = asc_prt_line(cp, leftlen, ! 8618: " Synchronous Transfer:"); ! 8619: ASC_PRT_NEXT(); ! 8620: for (i = 0; i <= ADV_MAX_TID; i++) { ! 8621: len = asc_prt_line(cp, leftlen, " %c", ! 8622: (ep->sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 8623: ASC_PRT_NEXT(); ! 8624: } ! 8625: len = asc_prt_line(cp, leftlen, "\n"); ! 8626: ASC_PRT_NEXT(); ! 8627: ! 8628: len = asc_prt_line(cp, leftlen, ! 8629: " Ultra Transfer: "); ! 8630: ASC_PRT_NEXT(); ! 8631: for (i = 0; i <= ADV_MAX_TID; i++) { ! 8632: len = asc_prt_line(cp, leftlen, " %c", ! 8633: (ep->ultra_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 8634: ASC_PRT_NEXT(); ! 8635: } ! 8636: len = asc_prt_line(cp, leftlen, "\n"); ! 8637: ASC_PRT_NEXT(); ! 8638: ! 8639: len = asc_prt_line(cp, leftlen, ! 8640: " Wide Transfer: "); ! 8641: ASC_PRT_NEXT(); ! 8642: for (i = 0; i <= ADV_MAX_TID; i++) { ! 8643: len = asc_prt_line(cp, leftlen, " %c", ! 8644: (ep->wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 8645: ASC_PRT_NEXT(); ! 8646: } ! 8647: len = asc_prt_line(cp, leftlen, "\n"); ! 8648: ASC_PRT_NEXT(); ! 8649: ! 8650: return totlen; ! 8651: } ! 8652: ! 8653: /* ! 8654: * asc_prt_driver_conf() ! 8655: * ! 8656: * Note: no single line should be greater than ASC_PRTLINE_SIZE, ! 8657: * cf. asc_prt_line(). ! 8658: * ! 8659: * Return the number of characters copied into 'cp'. No more than ! 8660: * 'cplen' characters will be copied to 'cp'. ! 8661: */ ! 8662: STATIC int ! 8663: asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen) ! 8664: { ! 8665: asc_board_t *boardp; ! 8666: int leftlen; ! 8667: int totlen; ! 8668: int len; ! 8669: int chip_scsi_id; ! 8670: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 8671: int i; ! 8672: #endif /* version >= v1.3.89 */ ! 8673: ! 8674: boardp = ASC_BOARDP(shp); ! 8675: ! 8676: leftlen = cplen; ! 8677: totlen = len = 0; ! 8678: ! 8679: len = asc_prt_line(cp, leftlen, ! 8680: "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n", ! 8681: shp->host_no); ! 8682: ASC_PRT_NEXT(); ! 8683: ! 8684: len = asc_prt_line(cp, leftlen, ! 8685: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89) ! 8686: " host_busy %u, last_reset %u, max_id %u, max_lun %u\n", ! 8687: shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun); ! 8688: #else /* version >= v1.3.89 */ ! 8689: " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n", ! 8690: shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun, ! 8691: shp->max_channel); ! 8692: #endif /* version >= v1.3.89 */ ! 8693: ASC_PRT_NEXT(); ! 8694: ! 8695: len = asc_prt_line(cp, leftlen, ! 8696: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57) ! 8697: " can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n", ! 8698: shp->can_queue, shp->this_id, shp->sg_tablesize, shp->cmd_per_lun); ! 8699: #else /* version >= v1.3.57 */ ! 8700: " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n", ! 8701: shp->unique_id, shp->can_queue, shp->this_id, shp->sg_tablesize, ! 8702: shp->cmd_per_lun); ! 8703: #endif /* version >= v1.3.57 */ ! 8704: ASC_PRT_NEXT(); ! 8705: ! 8706: len = asc_prt_line(cp, leftlen, ! 8707: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57) ! 8708: " unchecked_isa_dma %d, loaded_as_module %d\n", ! 8709: shp->unchecked_isa_dma, shp->loaded_as_module); ! 8710: #else /* version >= v1.3.57 */ ! 8711: " unchecked_isa_dma %d, use_clustering %d, loaded_as_module %d\n", ! 8712: shp->unchecked_isa_dma, shp->use_clustering, shp->loaded_as_module); ! 8713: #endif /* version >= v1.3.57 */ ! 8714: ASC_PRT_NEXT(); ! 8715: ! 8716: len = asc_prt_line(cp, leftlen, " flags %x, last_reset %x, jiffies %x\n", ! 8717: boardp->flags, boardp->last_reset, jiffies); ! 8718: ASC_PRT_NEXT(); ! 8719: ! 8720: if (ASC_NARROW_BOARD(boardp)) { ! 8721: chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; ! 8722: } else { ! 8723: chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; ! 8724: } ! 8725: ! 8726: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 8727: if (boardp->flags & ASC_SELECT_QUEUE_DEPTHS) { ! 8728: len = asc_prt_line(cp, leftlen, " queue_depth:"); ! 8729: ASC_PRT_NEXT(); ! 8730: for (i = 0; i <= ADV_MAX_TID; i++) { ! 8731: if ((chip_scsi_id == i) || ! 8732: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 8733: continue; ! 8734: } ! 8735: if (boardp->device[i] == NULL) { ! 8736: continue; ! 8737: } ! 8738: len = asc_prt_line(cp, leftlen, " %X:%d", ! 8739: i, boardp->device[i]->queue_depth); ! 8740: ASC_PRT_NEXT(); ! 8741: } ! 8742: len = asc_prt_line(cp, leftlen, "\n"); ! 8743: ASC_PRT_NEXT(); ! 8744: } ! 8745: #endif /* version >= v1.3.89 */ ! 8746: ! 8747: #if ASC_QUEUE_FLOW_CONTROL ! 8748: if (ASC_NARROW_BOARD(boardp)) { ! 8749: len = asc_prt_line(cp, leftlen, " queue_curr_depth:"); ! 8750: ASC_PRT_NEXT(); ! 8751: /* Use ASC_MAX_TID for Narrow Board. */ ! 8752: for (i = 0; i <= ASC_MAX_TID; i++) { ! 8753: if ((boardp->asc_dvc_cfg.chip_scsi_id == i) || ! 8754: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 8755: continue; ! 8756: } ! 8757: if (boardp->device[i] == NULL) { ! 8758: continue; ! 8759: } ! 8760: len = asc_prt_line(cp, leftlen, " %d:%d", ! 8761: i, boardp->device[i]->queue_curr_depth); ! 8762: ASC_PRT_NEXT(); ! 8763: } ! 8764: len = asc_prt_line(cp, leftlen, "\n"); ! 8765: ASC_PRT_NEXT(); ! 8766: ! 8767: len = asc_prt_line(cp, leftlen, " queue_count:"); ! 8768: ASC_PRT_NEXT(); ! 8769: /* Use ASC_MAX_TID for Narrow Board. */ ! 8770: for (i = 0; i <= ASC_MAX_TID; i++) { ! 8771: if ((boardp->asc_dvc_cfg.chip_scsi_id == i) || ! 8772: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 8773: continue; ! 8774: } ! 8775: if (boardp->device[i] == NULL) { ! 8776: continue; ! 8777: } ! 8778: len = asc_prt_line(cp, leftlen, " %d:%d", ! 8779: i, boardp->device[i]->queue_count); ! 8780: ASC_PRT_NEXT(); ! 8781: } ! 8782: len = asc_prt_line(cp, leftlen, "\n"); ! 8783: ASC_PRT_NEXT(); ! 8784: } ! 8785: #endif /* ASC_QUEUE_FLOW_CONTROL */ ! 8786: ! 8787: return totlen; ! 8788: } ! 8789: ! 8790: /* ! 8791: * asc_prt_asc_board_info() ! 8792: * ! 8793: * Print dynamic board configuration information. ! 8794: * ! 8795: * Note: no single line should be greater than ASC_PRTLINE_SIZE, ! 8796: * cf. asc_prt_line(). ! 8797: * ! 8798: * Return the number of characters copied into 'cp'. No more than ! 8799: * 'cplen' characters will be copied to 'cp'. ! 8800: */ ! 8801: STATIC int ! 8802: asc_prt_asc_board_info(struct Scsi_Host *shp, char *cp, int cplen) ! 8803: { ! 8804: asc_board_t *boardp; ! 8805: int leftlen; ! 8806: int totlen; ! 8807: int len; ! 8808: ASC_DVC_VAR *v; ! 8809: ASC_DVC_CFG *c; ! 8810: int i; ! 8811: ! 8812: boardp = ASC_BOARDP(shp); ! 8813: v = &boardp->dvc_var.asc_dvc_var; ! 8814: c = &boardp->dvc_cfg.asc_dvc_cfg; ! 8815: ! 8816: leftlen = cplen; ! 8817: totlen = len = 0; ! 8818: ! 8819: len = asc_prt_line(cp, leftlen, ! 8820: "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n", ! 8821: shp->host_no); ! 8822: ASC_PRT_NEXT(); ! 8823: ! 8824: len = asc_prt_line(cp, leftlen, ! 8825: " chip_version %u, lib_version %x, lib_serial_no %u, mcode_date %x\n", ! 8826: c->chip_version, c->lib_version, c->lib_serial_no, c->mcode_date); ! 8827: ASC_PRT_NEXT(); ! 8828: ! 8829: len = asc_prt_line(cp, leftlen, ! 8830: " mcode_version %x, err_code %u\n", ! 8831: c->mcode_version, v->err_code); ! 8832: ASC_PRT_NEXT(); ! 8833: ! 8834: /* Current number of commands waiting for the host. */ ! 8835: len = asc_prt_line(cp, leftlen, ! 8836: " Total Command Pending: %d\n", v->cur_total_qng); ! 8837: ASC_PRT_NEXT(); ! 8838: ! 8839: len = asc_prt_line(cp, leftlen, ! 8840: " Command Queuing:"); ! 8841: ASC_PRT_NEXT(); ! 8842: for (i = 0; i <= ASC_MAX_TID; i++) { ! 8843: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) || ! 8844: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 8845: continue; ! 8846: } ! 8847: len = asc_prt_line(cp, leftlen, " %d:%c", ! 8848: i, (v->use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 8849: ASC_PRT_NEXT(); ! 8850: } ! 8851: len = asc_prt_line(cp, leftlen, "\n"); ! 8852: ASC_PRT_NEXT(); ! 8853: ! 8854: /* Current number of commands waiting for a device. */ ! 8855: len = asc_prt_line(cp, leftlen, ! 8856: " Command Queue Pending:"); ! 8857: ASC_PRT_NEXT(); ! 8858: for (i = 0; i <= ASC_MAX_TID; i++) { ! 8859: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) || ! 8860: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 8861: continue; ! 8862: } ! 8863: len = asc_prt_line(cp, leftlen, " %d:%u", i, v->cur_dvc_qng[i]); ! 8864: ASC_PRT_NEXT(); ! 8865: } ! 8866: len = asc_prt_line(cp, leftlen, "\n"); ! 8867: ASC_PRT_NEXT(); ! 8868: ! 8869: /* Current limit on number of commands that can be sent to a device. */ ! 8870: len = asc_prt_line(cp, leftlen, ! 8871: " Command Queue Limit:"); ! 8872: ASC_PRT_NEXT(); ! 8873: for (i = 0; i <= ASC_MAX_TID; i++) { ! 8874: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) || ! 8875: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 8876: continue; ! 8877: } ! 8878: len = asc_prt_line(cp, leftlen, " %d:%u", i, v->max_dvc_qng[i]); ! 8879: ASC_PRT_NEXT(); ! 8880: } ! 8881: len = asc_prt_line(cp, leftlen, "\n"); ! 8882: ASC_PRT_NEXT(); ! 8883: ! 8884: /* Indicate whether the device has returned queue full status. */ ! 8885: len = asc_prt_line(cp, leftlen, ! 8886: " Command Queue Full:"); ! 8887: ASC_PRT_NEXT(); ! 8888: for (i = 0; i <= ASC_MAX_TID; i++) { ! 8889: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) || ! 8890: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 8891: continue; ! 8892: } ! 8893: if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) { ! 8894: len = asc_prt_line(cp, leftlen, " %d:Y-%d", ! 8895: i, boardp->queue_full_cnt[i]); ! 8896: } else { ! 8897: len = asc_prt_line(cp, leftlen, " %d:N", i); ! 8898: } ! 8899: ASC_PRT_NEXT(); ! 8900: } ! 8901: len = asc_prt_line(cp, leftlen, "\n"); ! 8902: ASC_PRT_NEXT(); ! 8903: ! 8904: len = asc_prt_line(cp, leftlen, ! 8905: " Synchronous Transfer:"); ! 8906: ASC_PRT_NEXT(); ! 8907: for (i = 0; i <= ASC_MAX_TID; i++) { ! 8908: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) || ! 8909: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 8910: continue; ! 8911: } ! 8912: len = asc_prt_line(cp, leftlen, " %d:%c", ! 8913: i, (v->sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 8914: ASC_PRT_NEXT(); ! 8915: } ! 8916: len = asc_prt_line(cp, leftlen, "\n"); ! 8917: ASC_PRT_NEXT(); ! 8918: ! 8919: for (i = 0; i <= ASC_MAX_TID; i++) { ! 8920: uchar syn_period_ix; ! 8921: ! 8922: if ((boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id == i) || ! 8923: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 8924: continue; ! 8925: } ! 8926: if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { ! 8927: continue; ! 8928: } ! 8929: syn_period_ix = (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index - 1); ! 8930: len = asc_prt_line(cp, leftlen, " %d:", i); ! 8931: ASC_PRT_NEXT(); ! 8932: ! 8933: len = asc_prt_line(cp, leftlen, ! 8934: " Transfer Period Factor: %d (%d.%d Mhz),", ! 8935: v->sdtr_period_tbl[syn_period_ix], ! 8936: 250 / v->sdtr_period_tbl[syn_period_ix], ! 8937: ASC_TENTHS(250, v->sdtr_period_tbl[syn_period_ix])); ! 8938: ASC_PRT_NEXT(); ! 8939: ! 8940: len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d\n", ! 8941: boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET); ! 8942: ASC_PRT_NEXT(); ! 8943: } ! 8944: ! 8945: return totlen; ! 8946: } ! 8947: ! 8948: /* ! 8949: * asc_prt_adv_board_info() ! 8950: * ! 8951: * Print dynamic board configuration information. ! 8952: * ! 8953: * Note: no single line should be greater than ASC_PRTLINE_SIZE, ! 8954: * cf. asc_prt_line(). ! 8955: * ! 8956: * Return the number of characters copied into 'cp'. No more than ! 8957: * 'cplen' characters will be copied to 'cp'. ! 8958: */ ! 8959: STATIC int ! 8960: asc_prt_adv_board_info(struct Scsi_Host *shp, char *cp, int cplen) ! 8961: { ! 8962: asc_board_t *boardp; ! 8963: int leftlen; ! 8964: int totlen; ! 8965: int len; ! 8966: int i; ! 8967: ADV_DVC_VAR *v; ! 8968: ADV_DVC_CFG *c; ! 8969: AdvPortAddr iop_base; ! 8970: ushort chip_scsi_id; ! 8971: ushort lramword; ! 8972: uchar lrambyte; ! 8973: ushort sdtr_able; ! 8974: ushort period; ! 8975: ! 8976: boardp = ASC_BOARDP(shp); ! 8977: v = &boardp->dvc_var.adv_dvc_var; ! 8978: c = &boardp->dvc_cfg.adv_dvc_cfg; ! 8979: iop_base = v->iop_base; ! 8980: chip_scsi_id = v->chip_scsi_id; ! 8981: ! 8982: leftlen = cplen; ! 8983: totlen = len = 0; ! 8984: ! 8985: len = asc_prt_line(cp, leftlen, ! 8986: "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n", ! 8987: shp->host_no); ! 8988: ASC_PRT_NEXT(); ! 8989: ! 8990: len = asc_prt_line(cp, leftlen, ! 8991: " iop_base %lx, cable_detect: %X, err_code %u, idle_cmd_done %u\n", ! 8992: v->iop_base, ! 8993: AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1) & CABLE_DETECT, ! 8994: v->err_code, v->idle_cmd_done); ! 8995: ASC_PRT_NEXT(); ! 8996: ! 8997: len = asc_prt_line(cp, leftlen, ! 8998: " chip_version %u, lib_version %x, mcode_date %x, mcode_version %x\n", ! 8999: c->chip_version, c->lib_version, c->mcode_date, c->mcode_version); ! 9000: ASC_PRT_NEXT(); ! 9001: ! 9002: AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, lramword); ! 9003: len = asc_prt_line(cp, leftlen, ! 9004: " Queuing Enabled:"); ! 9005: ASC_PRT_NEXT(); ! 9006: for (i = 0; i <= ADV_MAX_TID; i++) { ! 9007: if ((chip_scsi_id == i) || ! 9008: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 9009: continue; ! 9010: } ! 9011: ! 9012: len = asc_prt_line(cp, leftlen, " %X:%c", ! 9013: i, (lramword & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 9014: ASC_PRT_NEXT(); ! 9015: } ! 9016: len = asc_prt_line(cp, leftlen, "\n"); ! 9017: ASC_PRT_NEXT(); ! 9018: ! 9019: len = asc_prt_line(cp, leftlen, ! 9020: " Queue Limit:"); ! 9021: ASC_PRT_NEXT(); ! 9022: for (i = 0; i <= ADV_MAX_TID; i++) { ! 9023: if ((chip_scsi_id == i) || ! 9024: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 9025: continue; ! 9026: } ! 9027: ! 9028: AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i, lrambyte); ! 9029: ! 9030: len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte); ! 9031: ASC_PRT_NEXT(); ! 9032: } ! 9033: len = asc_prt_line(cp, leftlen, "\n"); ! 9034: ASC_PRT_NEXT(); ! 9035: ! 9036: len = asc_prt_line(cp, leftlen, ! 9037: " Command Pending:"); ! 9038: ASC_PRT_NEXT(); ! 9039: for (i = 0; i <= ADV_MAX_TID; i++) { ! 9040: if ((chip_scsi_id == i) || ! 9041: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 9042: continue; ! 9043: } ! 9044: ! 9045: AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i, lrambyte); ! 9046: ! 9047: len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte); ! 9048: ASC_PRT_NEXT(); ! 9049: } ! 9050: len = asc_prt_line(cp, leftlen, "\n"); ! 9051: ASC_PRT_NEXT(); ! 9052: ! 9053: AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, lramword); ! 9054: len = asc_prt_line(cp, leftlen, ! 9055: " Wide Enabled:"); ! 9056: ASC_PRT_NEXT(); ! 9057: for (i = 0; i <= ADV_MAX_TID; i++) { ! 9058: if ((chip_scsi_id == i) || ! 9059: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 9060: continue; ! 9061: } ! 9062: ! 9063: len = asc_prt_line(cp, leftlen, " %X:%c", ! 9064: i, (lramword & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 9065: ASC_PRT_NEXT(); ! 9066: } ! 9067: len = asc_prt_line(cp, leftlen, "\n"); ! 9068: ASC_PRT_NEXT(); ! 9069: ! 9070: len = asc_prt_line(cp, leftlen, ! 9071: " Transfer Bit Width:"); ! 9072: ASC_PRT_NEXT(); ! 9073: for (i = 0; i <= ADV_MAX_TID; i++) { ! 9074: if ((chip_scsi_id == i) || ! 9075: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 9076: continue; ! 9077: } ! 9078: ! 9079: AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i), ! 9080: lramword); ! 9081: len = asc_prt_line(cp, leftlen, " %X:%d", ! 9082: i, (lramword & 0x8000) ? 16 : 8); ! 9083: ASC_PRT_NEXT(); ! 9084: } ! 9085: len = asc_prt_line(cp, leftlen, "\n"); ! 9086: ASC_PRT_NEXT(); ! 9087: ! 9088: AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); ! 9089: len = asc_prt_line(cp, leftlen, ! 9090: " Synchronous Enabled:"); ! 9091: ASC_PRT_NEXT(); ! 9092: for (i = 0; i <= ADV_MAX_TID; i++) { ! 9093: if ((chip_scsi_id == i) || ! 9094: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 9095: continue; ! 9096: } ! 9097: ! 9098: len = asc_prt_line(cp, leftlen, " %X:%c", ! 9099: i, (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); ! 9100: ASC_PRT_NEXT(); ! 9101: } ! 9102: len = asc_prt_line(cp, leftlen, "\n"); ! 9103: ASC_PRT_NEXT(); ! 9104: ! 9105: for (i = 0; i <= ADV_MAX_TID; i++) { ! 9106: ! 9107: AdvReadWordLram(iop_base, ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i), ! 9108: lramword); ! 9109: lramword &= ~0x8000; ! 9110: ! 9111: if ((chip_scsi_id == i) || ! 9112: ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0) || ! 9113: (lramword == 0)) { ! 9114: continue; ! 9115: } ! 9116: ! 9117: len = asc_prt_line(cp, leftlen, " %X:", i); ! 9118: ASC_PRT_NEXT(); ! 9119: ! 9120: period = (((lramword >> 8) * 25) + 50)/4; ! 9121: ! 9122: len = asc_prt_line(cp, leftlen, ! 9123: " Transfer Period Factor: %d (%d.%d Mhz),", ! 9124: period, 250/period, ASC_TENTHS(250, period)); ! 9125: ASC_PRT_NEXT(); ! 9126: ! 9127: len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d\n", ! 9128: lramword & 0x1F); ! 9129: ASC_PRT_NEXT(); ! 9130: } ! 9131: ! 9132: return totlen; ! 9133: } ! 9134: ! 9135: /* ! 9136: * asc_proc_copy() ! 9137: * ! 9138: * Copy proc information to a read buffer taking into account the current ! 9139: * read offset in the file and the remaining space in the read buffer. ! 9140: */ ! 9141: STATIC int ! 9142: asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen, ! 9143: char *cp, int cplen) ! 9144: { ! 9145: int cnt = 0; ! 9146: ! 9147: ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n", ! 9148: (unsigned) offset, (unsigned) advoffset, cplen); ! 9149: if (offset <= advoffset) { ! 9150: /* Read offset below current offset, copy everything. */ ! 9151: cnt = ASC_MIN(cplen, leftlen); ! 9152: ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n", ! 9153: (unsigned) curbuf, (unsigned) cp, cnt); ! 9154: memcpy(curbuf, cp, cnt); ! 9155: } else if (offset < advoffset + cplen) { ! 9156: /* Read offset within current range, partial copy. */ ! 9157: cnt = (advoffset + cplen) - offset; ! 9158: cp = (cp + cplen) - cnt; ! 9159: cnt = ASC_MIN(cnt, leftlen); ! 9160: ASC_DBG3(2, "asc_proc_copy: curbuf %x, cp %x, cnt %d\n", ! 9161: (unsigned) curbuf, (unsigned) cp, cnt); ! 9162: memcpy(curbuf, cp, cnt); ! 9163: } ! 9164: return cnt; ! 9165: } ! 9166: ! 9167: /* ! 9168: * asc_prt_line() ! 9169: * ! 9170: * If 'cp' is NULL print to the console, otherwise print to a buffer. ! 9171: * ! 9172: * Return 0 if printing to the console, otherwise return the number of ! 9173: * bytes written to the buffer. ! 9174: * ! 9175: * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack ! 9176: * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes. ! 9177: */ ! 9178: STATIC int ! 9179: asc_prt_line(char *buf, int buflen, char *fmt, ...) ! 9180: { ! 9181: va_list args; ! 9182: int ret; ! 9183: char s[ASC_PRTLINE_SIZE]; ! 9184: ! 9185: va_start(args, fmt); ! 9186: ret = vsprintf(s, fmt, args); ! 9187: ASC_ASSERT(ret < ASC_PRTLINE_SIZE); ! 9188: if (buf == NULL) { ! 9189: (void) printk(s); ! 9190: ret = 0; ! 9191: } else { ! 9192: ret = ASC_MIN(buflen, ret); ! 9193: memcpy(buf, s, ret); ! 9194: } ! 9195: va_end(args); ! 9196: return ret; ! 9197: } ! 9198: #endif /* version >= v1.3.0 */ ! 9199: ! 9200: ! 9201: /* ! 9202: * --- Functions Required by the Asc Library ! 9203: */ ! 9204: ! 9205: /* ! 9206: * Delay for 'n' milliseconds. Don't use the 'jiffies' ! 9207: * global variable which is incremented once every 5 ms ! 9208: * from a timer interrupt, because this function may be ! 9209: * called when interrupts are disabled. ! 9210: */ ! 9211: STATIC void ! 9212: DvcSleepMilliSecond(ulong n) ! 9213: { ! 9214: ulong i; ! 9215: ! 9216: ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", n); ! 9217: for (i = 0; i < n; i++) { ! 9218: udelay(1000); ! 9219: } ! 9220: } ! 9221: ! 9222: STATIC int ! 9223: DvcEnterCritical(void) ! 9224: { ! 9225: int flags; ! 9226: ! 9227: save_flags(flags); ! 9228: cli(); ! 9229: return flags; ! 9230: } ! 9231: ! 9232: STATIC void ! 9233: DvcLeaveCritical(int flags) ! 9234: { ! 9235: restore_flags(flags); ! 9236: } ! 9237: ! 9238: STATIC ulong ! 9239: DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len, ! 9240: ASC_SG_HEAD *asc_sg_head_ptr) ! 9241: { ! 9242: ulong buf_size; ! 9243: ! 9244: buf_size = buf_len; ! 9245: asc_sg_head_ptr->entry_cnt = 1; ! 9246: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0) ! 9247: asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr; ! 9248: #else /* version >= v2.0.0 */ ! 9249: asc_sg_head_ptr->sg_list[0].addr = virt_to_bus(buf_addr); ! 9250: #endif /* version >= v2.0.0 */ ! 9251: asc_sg_head_ptr->sg_list[0].bytes = buf_size; ! 9252: return buf_size; ! 9253: } ! 9254: ! 9255: /* ! 9256: * void ! 9257: * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words) ! 9258: * ! 9259: * Calling/Exit State: ! 9260: * none ! 9261: * ! 9262: * Description: ! 9263: * Output an ASC_SCSI_Q structure to the chip ! 9264: */ ! 9265: STATIC void ! 9266: DvcPutScsiQ(PortAddr iop_base, ushort s_addr, ushort *outbuf, int words) ! 9267: { ! 9268: int i; ! 9269: ! 9270: ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", (uchar *) outbuf, 2 * words); ! 9271: AscSetChipLramAddr(iop_base, s_addr); ! 9272: for (i = 0; i < words; i++, outbuf++) { ! 9273: if (i == 2 || i == 10) { ! 9274: continue; ! 9275: } ! 9276: AscSetChipLramDataNoSwap(iop_base, *outbuf); ! 9277: } ! 9278: } ! 9279: ! 9280: /* ! 9281: * void ! 9282: * DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words) ! 9283: * ! 9284: * Calling/Exit State: ! 9285: * none ! 9286: * ! 9287: * Description: ! 9288: * Input an ASC_QDONE_INFO structure from the chip ! 9289: */ ! 9290: STATIC void ! 9291: DvcGetQinfo(PortAddr iop_base, ushort s_addr, ushort *inbuf, int words) ! 9292: { ! 9293: int i; ! 9294: ! 9295: AscSetChipLramAddr(iop_base, s_addr); ! 9296: for (i = 0; i < words; i++, inbuf++) { ! 9297: if (i == 5) { ! 9298: continue; ! 9299: } ! 9300: *inbuf = AscGetChipLramDataNoSwap(iop_base); ! 9301: } ! 9302: ASC_DBG_PRT_HEX(2, "DvcGetQinfo", (uchar *) inbuf, 2 * words); ! 9303: } ! 9304: ! 9305: /* ! 9306: * void DvcOutPortWords(ushort iop_base, ushort &outbuf, int words) ! 9307: * ! 9308: * Calling/Exit State: ! 9309: * none ! 9310: * ! 9311: * Description: ! 9312: * output a buffer to an i/o port address ! 9313: */ ! 9314: STATIC void ! 9315: DvcOutPortWords(ushort iop_base, ushort *outbuf, int words) ! 9316: { ! 9317: int i; ! 9318: ! 9319: for (i = 0; i < words; i++, outbuf++) ! 9320: outpw(iop_base, *outbuf); ! 9321: } ! 9322: ! 9323: /* ! 9324: * void DvcInPortWords(ushort iop_base, ushort &outbuf, int words) ! 9325: * ! 9326: * Calling/Exit State: ! 9327: * none ! 9328: * ! 9329: * Description: ! 9330: * input a buffer from an i/o port address ! 9331: */ ! 9332: STATIC void ! 9333: DvcInPortWords(ushort iop_base, ushort *inbuf, int words) ! 9334: { ! 9335: int i; ! 9336: ! 9337: for (i = 0; i < words; i++, inbuf++) ! 9338: *inbuf = inpw(iop_base); ! 9339: } ! 9340: ! 9341: /* ! 9342: * void DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords) ! 9343: * ! 9344: * Calling/Exit State: ! 9345: * none ! 9346: * ! 9347: * Description: ! 9348: * output a buffer of 32-bit integers to an i/o port address in ! 9349: * 16 bit integer units ! 9350: */ ! 9351: STATIC void ! 9352: DvcOutPortDWords(PortAddr port, ulong *pdw, int dwords) ! 9353: { ! 9354: int i; ! 9355: int words; ! 9356: ushort *pw; ! 9357: ! 9358: pw = (ushort *) pdw; ! 9359: words = dwords << 1; ! 9360: for(i = 0; i < words; i++, pw++) { ! 9361: outpw(port, *pw); ! 9362: } ! 9363: return; ! 9364: } ! 9365: ! 9366: /* ! 9367: * Read a PCI configuration byte. ! 9368: */ ! 9369: ASC_INITFUNC( ! 9370: STATIC uchar ! 9371: DvcReadPCIConfigByte( ! 9372: ASC_DVC_VAR asc_ptr_type *asc_dvc, ! 9373: ushort offset) ! 9374: ) ! 9375: { ! 9376: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) ! 9377: #ifdef ASC_CONFIG_PCI ! 9378: PCI_DATA pciData; ! 9379: ! 9380: pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info); ! 9381: pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info); ! 9382: pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info); ! 9383: pciData.offset = offset; ! 9384: pciData.type = pci_scan_method; ! 9385: return asc_get_cfg_byte(&pciData); ! 9386: #else /* ASC_CONFIG_PCI */ ! 9387: return 0; ! 9388: #endif /* ASC_CONFIG_PCI */ ! 9389: #else /* version >= v2.1.93 */ ! 9390: #ifdef CONFIG_PCI ! 9391: uchar byte_data; ! 9392: pcibios_read_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info), ! 9393: PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info), ! 9394: ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)), ! 9395: offset, &byte_data); ! 9396: return byte_data; ! 9397: #else /* CONFIG_PCI */ ! 9398: return 0; ! 9399: #endif /* CONFIG_PCI */ ! 9400: #endif /* version >= v2.1.93 */ ! 9401: } ! 9402: ! 9403: /* ! 9404: * Write a PCI configuration byte. ! 9405: */ ! 9406: ASC_INITFUNC( ! 9407: STATIC void ! 9408: DvcWritePCIConfigByte( ! 9409: ASC_DVC_VAR asc_ptr_type *asc_dvc, ! 9410: ushort offset, ! 9411: uchar byte_data) ! 9412: ) ! 9413: { ! 9414: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) ! 9415: #ifdef ASC_CONFIG_PCI ! 9416: PCI_DATA pciData; ! 9417: ! 9418: pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info); ! 9419: pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info); ! 9420: pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info); ! 9421: pciData.offset = offset; ! 9422: pciData.type = pci_scan_method; ! 9423: asc_put_cfg_byte(&pciData, byte_data); ! 9424: #endif /* ASC_CONFIG_PCI */ ! 9425: #else /* version >= v2.1.93 */ ! 9426: #ifdef CONFIG_PCI ! 9427: pcibios_write_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info), ! 9428: PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info), ! 9429: ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)), ! 9430: offset, byte_data); ! 9431: #endif /* CONFIG_PCI */ ! 9432: #endif /* version >= v2.1.93 */ ! 9433: } ! 9434: ! 9435: /* ! 9436: * Return the BIOS address of the adapter at the specified ! 9437: * I/O port and with the specified bus type. ! 9438: */ ! 9439: ASC_INITFUNC( ! 9440: STATIC ushort ! 9441: AscGetChipBiosAddress( ! 9442: PortAddr iop_base, ! 9443: ushort bus_type ! 9444: ) ! 9445: ) ! 9446: { ! 9447: ushort cfg_lsw ; ! 9448: ushort bios_addr ; ! 9449: ! 9450: /* ! 9451: * The PCI BIOS is re-located by the motherboard BIOS. Because ! 9452: * of this the driver can not determine where a PCI BIOS is ! 9453: * loaded and executes. ! 9454: */ ! 9455: if (bus_type & ASC_IS_PCI) ! 9456: { ! 9457: return(0); ! 9458: } ! 9459: ! 9460: if((bus_type & ASC_IS_EISA) != 0) ! 9461: { ! 9462: cfg_lsw = AscGetEisaChipCfg(iop_base) ; ! 9463: cfg_lsw &= 0x000F ; ! 9464: bios_addr = (ushort)(ASC_BIOS_MIN_ADDR + ! 9465: (cfg_lsw * ASC_BIOS_BANK_SIZE)) ; ! 9466: return(bios_addr) ; ! 9467: }/* if */ ! 9468: ! 9469: cfg_lsw = AscGetChipCfgLsw(iop_base) ; ! 9470: ! 9471: /* ! 9472: * ISA PnP uses the top bit as the 32K BIOS flag ! 9473: */ ! 9474: if (bus_type == ASC_IS_ISAPNP) ! 9475: { ! 9476: cfg_lsw &= 0x7FFF; ! 9477: }/* if */ ! 9478: ! 9479: bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) + ! 9480: ASC_BIOS_MIN_ADDR) ; ! 9481: return(bios_addr) ; ! 9482: } ! 9483: ! 9484: ! 9485: /* ! 9486: * --- Functions Required by the Adv Library ! 9487: */ ! 9488: ! 9489: /* ! 9490: * DvcGetPhyAddr() ! 9491: * ! 9492: * Return the physical address of 'vaddr' and set '*lenp' to the ! 9493: * number of physically contiguous bytes that follow 'vaddr'. ! 9494: * 'flag' indicates the type of structure whose physical address ! 9495: * is being translated. ! 9496: * ! 9497: * Note: Because Linux currently doesn't page the kernel and all ! 9498: * kernel buffers are physically contiguous, leave '*lenp' unchanged. ! 9499: */ ! 9500: ulong ! 9501: DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq, ! 9502: uchar *vaddr, long *lenp, int flag) ! 9503: { ! 9504: ulong paddr; ! 9505: ! 9506: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0) ! 9507: paddr = (ulong) vaddr; ! 9508: #else /* version >= v2.0.0 */ ! 9509: paddr = virt_to_bus(vaddr); ! 9510: #endif /* version >= v2.0.0 */ ! 9511: ! 9512: ASC_DBG4(4, ! 9513: "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n", ! 9514: (ulong) vaddr, (ulong) lenp, (ulong) *((ulong *) lenp), paddr); ! 9515: ! 9516: return paddr; ! 9517: } ! 9518: ! 9519: /* ! 9520: * Read a PCI configuration byte. ! 9521: */ ! 9522: ASC_INITFUNC( ! 9523: STATIC uchar ! 9524: DvcAdvReadPCIConfigByte( ! 9525: ADV_DVC_VAR *asc_dvc, ! 9526: ushort offset) ! 9527: ) ! 9528: { ! 9529: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) ! 9530: #ifdef ASC_CONFIG_PCI ! 9531: PCI_DATA pciData; ! 9532: ! 9533: pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info); ! 9534: pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info); ! 9535: pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info); ! 9536: pciData.offset = offset; ! 9537: pciData.type = pci_scan_method; ! 9538: return asc_get_cfg_byte(&pciData); ! 9539: #else /* ASC_CONFIG_PCI */ ! 9540: return 0; ! 9541: #endif /* ASC_CONFIG_PCI */ ! 9542: #else /* version >= v2.1.93 */ ! 9543: #ifdef CONFIG_PCI ! 9544: uchar byte_data; ! 9545: pcibios_read_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info), ! 9546: PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info), ! 9547: ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)), ! 9548: offset, &byte_data); ! 9549: return byte_data; ! 9550: #else /* CONFIG_PCI */ ! 9551: return 0; ! 9552: #endif /* CONFIG_PCI */ ! 9553: #endif /* version >= v2.1.93 */ ! 9554: } ! 9555: ! 9556: /* ! 9557: * Write a PCI configuration byte. ! 9558: */ ! 9559: ASC_INITFUNC( ! 9560: STATIC void ! 9561: DvcAdvWritePCIConfigByte( ! 9562: ADV_DVC_VAR *asc_dvc, ! 9563: ushort offset, ! 9564: uchar byte_data) ! 9565: ) ! 9566: { ! 9567: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,93) ! 9568: #ifdef ASC_CONFIG_PCI ! 9569: PCI_DATA pciData; ! 9570: ! 9571: pciData.bus = ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info); ! 9572: pciData.slot = ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info); ! 9573: pciData.func = ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info); ! 9574: pciData.offset = offset; ! 9575: pciData.type = pci_scan_method; ! 9576: asc_put_cfg_byte(&pciData, byte_data); ! 9577: #endif /* ASC_CONFIG_PCI */ ! 9578: #else /* version >= v2.1.93 */ ! 9579: #ifdef CONFIG_PCI ! 9580: pcibios_write_config_byte(ASC_PCI_ID2BUS(asc_dvc->cfg->pci_slot_info), ! 9581: PCI_DEVFN(ASC_PCI_ID2DEV(asc_dvc->cfg->pci_slot_info), ! 9582: ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info)), ! 9583: offset, byte_data); ! 9584: #endif /* CONFIG_PCI */ ! 9585: #endif /* version >= v2.1.93 */ ! 9586: } ! 9587: ! 9588: /* ! 9589: * --- Tracing and Debugging Functions ! 9590: */ ! 9591: ! 9592: #ifdef ADVANSYS_STATS ! 9593: /* ! 9594: * asc_prt_board_stats() ! 9595: * ! 9596: * Note: no single line should be greater than ASC_PRTLINE_SIZE, ! 9597: * cf. asc_prt_line(). ! 9598: * ! 9599: * Return the number of characters copied into 'cp'. No more than ! 9600: * 'cplen' characters will be copied to 'cp'. ! 9601: */ ! 9602: STATIC int ! 9603: asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen) ! 9604: { ! 9605: int leftlen; ! 9606: int totlen; ! 9607: int len; ! 9608: struct asc_stats *s; ! 9609: int i; ! 9610: ushort chip_scsi_id; ! 9611: asc_board_t *boardp; ! 9612: asc_queue_t *active; ! 9613: asc_queue_t *waiting; ! 9614: ! 9615: leftlen = cplen; ! 9616: totlen = len = 0; ! 9617: ! 9618: boardp = ASC_BOARDP(shp); ! 9619: s = &boardp->asc_stats; ! 9620: ! 9621: len = asc_prt_line(cp, leftlen, ! 9622: "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n", shp->host_no); ! 9623: ASC_PRT_NEXT(); ! 9624: ! 9625: len = asc_prt_line(cp, leftlen, ! 9626: " command %lu, queuecommand %lu, abort %lu, reset %lu, biosparam %lu\n", ! 9627: s->command, s->queuecommand, s->abort, s->reset, s->biosparam); ! 9628: ASC_PRT_NEXT(); ! 9629: ! 9630: len = asc_prt_line(cp, leftlen, ! 9631: " interrupt %lu, callback %lu, done %lu\n", ! 9632: s->interrupt, s->callback, s->done); ! 9633: ASC_PRT_NEXT(); ! 9634: ! 9635: len = asc_prt_line(cp, leftlen, ! 9636: " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n", ! 9637: s->exe_noerror, s->exe_busy, s->exe_error, s->exe_unknown); ! 9638: ASC_PRT_NEXT(); ! 9639: ! 9640: if (ASC_NARROW_BOARD(boardp)) { ! 9641: len = asc_prt_line(cp, leftlen, ! 9642: " build_error %lu\n", ! 9643: s->build_error); ! 9644: } else { ! 9645: len = asc_prt_line(cp, leftlen, ! 9646: " build_error %lu, build_noreq %lu, build_nosg %lu\n", ! 9647: s->build_error, s->adv_build_noreq, s->adv_build_nosg); ! 9648: } ! 9649: ASC_PRT_NEXT(); ! 9650: ! 9651: /* ! 9652: * Display data transfer statistics. ! 9653: */ ! 9654: if (s->cont_cnt > 0) { ! 9655: len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt); ! 9656: ASC_PRT_NEXT(); ! 9657: ! 9658: len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ", ! 9659: s->cont_xfer/2, ! 9660: ASC_TENTHS(s->cont_xfer, 2)); ! 9661: ASC_PRT_NEXT(); ! 9662: ! 9663: /* Contiguous transfer average size */ ! 9664: len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n", ! 9665: (s->cont_xfer/2)/s->cont_cnt, ! 9666: ASC_TENTHS((s->cont_xfer/2), s->cont_cnt)); ! 9667: ASC_PRT_NEXT(); ! 9668: } ! 9669: ! 9670: if (s->sg_cnt > 0) { ! 9671: ! 9672: len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ", ! 9673: s->sg_cnt, s->sg_elem); ! 9674: ASC_PRT_NEXT(); ! 9675: ! 9676: len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n", ! 9677: s->sg_xfer/2, ! 9678: ASC_TENTHS(s->sg_xfer, 2)); ! 9679: ASC_PRT_NEXT(); ! 9680: ! 9681: /* Scatter gather transfer statistics */ ! 9682: len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ", ! 9683: s->sg_elem/s->sg_cnt, ! 9684: ASC_TENTHS(s->sg_elem, s->sg_cnt)); ! 9685: ASC_PRT_NEXT(); ! 9686: ! 9687: len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ", ! 9688: (s->sg_xfer/2)/s->sg_elem, ! 9689: ASC_TENTHS((s->sg_xfer/2), s->sg_elem)); ! 9690: ASC_PRT_NEXT(); ! 9691: ! 9692: len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n", ! 9693: (s->sg_xfer/2)/s->sg_cnt, ! 9694: ASC_TENTHS((s->sg_xfer/2), s->sg_cnt)); ! 9695: ASC_PRT_NEXT(); ! 9696: } ! 9697: ! 9698: /* ! 9699: * Display request queuing statistics. ! 9700: */ ! 9701: len = asc_prt_line(cp, leftlen, ! 9702: " Active and Waiting Request Queues (Time Unit: %d HZ):\n", HZ); ! 9703: ASC_PRT_NEXT(); ! 9704: ! 9705: active = &ASC_BOARDP(shp)->active; ! 9706: waiting = &ASC_BOARDP(shp)->waiting; ! 9707: ! 9708: if (ASC_NARROW_BOARD(boardp)) { ! 9709: chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; ! 9710: } else { ! 9711: chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; ! 9712: } ! 9713: ! 9714: for (i = 0; i <= ADV_MAX_TID; i++) { ! 9715: ! 9716: if ((chip_scsi_id == i) || ! 9717: ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { ! 9718: continue; ! 9719: } ! 9720: ! 9721: if (active->q_tot_cnt[i] > 0 || waiting->q_tot_cnt[i] > 0) { ! 9722: len = asc_prt_line(cp, leftlen, " target %d\n", i); ! 9723: ASC_PRT_NEXT(); ! 9724: ! 9725: len = asc_prt_line(cp, leftlen, ! 9726: " active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n", ! 9727: active->q_cur_cnt[i], active->q_max_cnt[i], ! 9728: active->q_tot_cnt[i], ! 9729: active->q_min_tim[i], active->q_max_tim[i], ! 9730: (active->q_tot_cnt[i] == 0) ? 0 : ! 9731: (active->q_tot_tim[i]/active->q_tot_cnt[i]), ! 9732: (active->q_tot_cnt[i] == 0) ? 0 : ! 9733: ASC_TENTHS(active->q_tot_tim[i], active->q_tot_cnt[i])); ! 9734: ASC_PRT_NEXT(); ! 9735: ! 9736: len = asc_prt_line(cp, leftlen, ! 9737: " waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n", ! 9738: waiting->q_cur_cnt[i], waiting->q_max_cnt[i], ! 9739: waiting->q_tot_cnt[i], ! 9740: waiting->q_min_tim[i], waiting->q_max_tim[i], ! 9741: (waiting->q_tot_cnt[i] == 0) ? 0 : ! 9742: (waiting->q_tot_tim[i]/waiting->q_tot_cnt[i]), ! 9743: (waiting->q_tot_cnt[i] == 0) ? 0 : ! 9744: ASC_TENTHS(waiting->q_tot_tim[i], waiting->q_tot_cnt[i])); ! 9745: ASC_PRT_NEXT(); ! 9746: } ! 9747: } ! 9748: ! 9749: return totlen; ! 9750: } ! 9751: #endif /* ADVANSYS_STATS */ ! 9752: ! 9753: #ifdef ADVANSYS_DEBUG ! 9754: /* ! 9755: * asc_prt_scsi_host() ! 9756: */ ! 9757: STATIC void ! 9758: asc_prt_scsi_host(struct Scsi_Host *s) ! 9759: { ! 9760: asc_board_t *boardp; ! 9761: ! 9762: boardp = ASC_BOARDP(s); ! 9763: ! 9764: printk("Scsi_Host at addr %x\n", (unsigned) s); ! 9765: printk( ! 9766: " next %x, extra_bytes %u, host_busy %u, host_no %d, last_reset %d,\n", ! 9767: (unsigned) s->next, s->extra_bytes, s->host_busy, s->host_no, ! 9768: (unsigned) s->last_reset); ! 9769: ! 9770: printk( ! 9771: " host_wait %x, host_queue %x, hostt %x, block %x,\n", ! 9772: (unsigned) s->host_wait, (unsigned) s->host_queue, ! 9773: (unsigned) s->hostt, (unsigned) s->block); ! 9774: ! 9775: printk( ! 9776: " wish_block %d, base %x, io_port %d, n_io_port %d, irq %d, dma_channel %d,\n", ! 9777: s->wish_block, (unsigned) s->base, s->io_port, s->n_io_port, ! 9778: s->irq, s->dma_channel); ! 9779: ! 9780: printk( ! 9781: " this_id %d, can_queue %d,\n", s->this_id, s->can_queue); ! 9782: ! 9783: printk( ! 9784: " cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d, loaded_as_module %d\n", ! 9785: s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma, ! 9786: s->loaded_as_module); ! 9787: ! 9788: if (ASC_NARROW_BOARD(boardp)) { ! 9789: asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var); ! 9790: asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg); ! 9791: } else { ! 9792: asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var); ! 9793: asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg); ! 9794: } ! 9795: } ! 9796: ! 9797: /* ! 9798: * asc_prt_scsi_cmnd() ! 9799: */ ! 9800: STATIC void ! 9801: asc_prt_scsi_cmnd(Scsi_Cmnd *s) ! 9802: { ! 9803: printk("Scsi_Cmnd at addr %x\n", (unsigned) s); ! 9804: ! 9805: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0) ! 9806: printk( ! 9807: " host %x, device %x, target %u, lun %u\n", ! 9808: (unsigned) s->host, (unsigned) s->device, s->target, s->lun); ! 9809: #else /* version >= v1.3.0 */ ! 9810: printk( ! 9811: " host %x, device %x, target %u, lun %u, channel %u,\n", ! 9812: (unsigned) s->host, (unsigned) s->device, s->target, s->lun, ! 9813: s->channel); ! 9814: #endif /* version >= v1.3.0 */ ! 9815: ! 9816: asc_prt_hex(" CDB", s->cmnd, s->cmd_len); ! 9817: ! 9818: printk( ! 9819: " use_sg %u, sglist_len %u, abort_reason %x\n", ! 9820: s->use_sg, s->sglist_len, s->abort_reason); ! 9821: ! 9822: #if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89) ! 9823: printk( ! 9824: " retries %d, allowed %d\n", ! 9825: s->retries, s->allowed); ! 9826: #else /* version >= v1.3.89 */ ! 9827: printk( ! 9828: " serial_number %x, serial_number_at_timeout %x, retries %d, allowed %d\n", ! 9829: (unsigned) s->serial_number, (unsigned) s->serial_number_at_timeout, ! 9830: s->retries, s->allowed); ! 9831: #endif /* version >= v1.3.89 */ ! 9832: ! 9833: printk( ! 9834: " timeout_per_command %d, timeout_total %d, timeout %d\n", ! 9835: s->timeout_per_command, s->timeout_total, s->timeout); ! 9836: ! 9837: printk( ! 9838: " internal_timeout %u, flags %u, this_count %d\n", ! 9839: s->internal_timeout, s->flags, s->this_count); ! 9840: ! 9841: printk( ! 9842: " scsi_done %x, done %x, host_scribble %x, result %x\n", ! 9843: (unsigned) s->scsi_done, (unsigned) s->done, ! 9844: (unsigned) s->host_scribble, s->result); ! 9845: ! 9846: printk( ! 9847: " tag %u, pid %u\n", ! 9848: (unsigned) s->tag, (unsigned) s->pid); ! 9849: } ! 9850: ! 9851: /* ! 9852: * asc_prt_asc_dvc_var() ! 9853: */ ! 9854: STATIC void ! 9855: asc_prt_asc_dvc_var(ASC_DVC_VAR *h) ! 9856: { ! 9857: printk("ASC_DVC_VAR at addr %x\n", (unsigned) h); ! 9858: ! 9859: printk( ! 9860: " iop_base %x, err_code %x, dvc_cntl %x, bug_fix_cntl %d,\n", ! 9861: h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl); ! 9862: ! 9863: printk( ! 9864: " bus_type %d, isr_callback %x, exe_callback %x, init_sdtr %x,\n", ! 9865: h->bus_type, (unsigned) h->isr_callback, (unsigned) h->exe_callback, ! 9866: (unsigned) h->init_sdtr); ! 9867: ! 9868: printk( ! 9869: " sdtr_done %x, use_tagged_qng %x, unit_not_ready %x, chip_no %x,\n", ! 9870: (unsigned) h->sdtr_done, (unsigned) h->use_tagged_qng, ! 9871: (unsigned) h->unit_not_ready, (unsigned) h->chip_no); ! 9872: ! 9873: printk( ! 9874: " queue_full_or_busy %x, start_motor %x, scsi_reset_wait %x, irq_no %x,\n", ! 9875: (unsigned) h->queue_full_or_busy, (unsigned) h->start_motor, ! 9876: (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no); ! 9877: ! 9878: printk( ! 9879: " is_in_int %x, max_total_qng %x, cur_total_qng %x, in_critical_cnt %x,\n", ! 9880: (unsigned) h->is_in_int, (unsigned) h->max_total_qng, ! 9881: (unsigned) h->cur_total_qng, (unsigned) h->in_critical_cnt); ! 9882: ! 9883: printk( ! 9884: " last_q_shortage %x, init_state %x, no_scam %x, pci_fix_asyn_xfer %x,\n", ! 9885: (unsigned) h->last_q_shortage, (unsigned) h->init_state, ! 9886: (unsigned) h->no_scam, (unsigned) h->pci_fix_asyn_xfer); ! 9887: ! 9888: printk( ! 9889: " cfg %x, saved_ptr2func %x\n", ! 9890: (unsigned) h->cfg, (unsigned) h->saved_ptr2func); ! 9891: } ! 9892: ! 9893: /* ! 9894: * asc_prt_asc_dvc_cfg() ! 9895: */ ! 9896: STATIC void ! 9897: asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h) ! 9898: { ! 9899: printk("ASC_DVC_CFG at addr %x\n", (unsigned) h); ! 9900: ! 9901: printk( ! 9902: " can_tagged_qng %x, cmd_qng_enabled %x, disc_enable %x, sdtr_enable %x,\n", ! 9903: h->can_tagged_qng, h->cmd_qng_enabled, h->disc_enable, ! 9904: h->sdtr_enable); ! 9905: ! 9906: printk( ! 9907: " chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n", ! 9908: h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel, ! 9909: h->chip_version); ! 9910: ! 9911: printk( ! 9912: " pci_device_id %d, lib_serial_no %x, lib_version %x, mcode_date %x,\n", ! 9913: h->pci_device_id, h->lib_serial_no, h->lib_version, h->mcode_date); ! 9914: ! 9915: printk( ! 9916: " mcode_version %d, overrun_buf %x\n", ! 9917: h->mcode_version, (unsigned) h->overrun_buf); ! 9918: } ! 9919: ! 9920: /* ! 9921: * asc_prt_asc_scsi_q() ! 9922: */ ! 9923: STATIC void ! 9924: asc_prt_asc_scsi_q(ASC_SCSI_Q *q) ! 9925: { ! 9926: ASC_SG_HEAD *sgp; ! 9927: int i; ! 9928: ! 9929: printk("ASC_SCSI_Q at addr %x\n", (unsigned) q); ! 9930: ! 9931: printk( ! 9932: " target_ix %u, target_lun %u, srb_ptr %x, tag_code %u,\n", ! 9933: q->q2.target_ix, q->q1.target_lun, ! 9934: (unsigned) q->q2.srb_ptr, q->q2.tag_code); ! 9935: ! 9936: printk( ! 9937: " data_addr %x, data_cnt %lu, sense_addr %x, sense_len %u,\n", ! 9938: (unsigned) q->q1.data_addr, q->q1.data_cnt, ! 9939: (unsigned) q->q1.sense_addr, q->q1.sense_len); ! 9940: ! 9941: printk( ! 9942: " cdbptr %x, cdb_len %u, sg_head %x, sg_queue_cnt %u\n", ! 9943: (unsigned) q->cdbptr, q->q2.cdb_len, ! 9944: (unsigned) q->sg_head, q->q1.sg_queue_cnt); ! 9945: ! 9946: if (q->sg_head) { ! 9947: sgp = q->sg_head; ! 9948: printk("ASC_SG_HEAD at addr %x\n", (unsigned) sgp); ! 9949: printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, sgp->queue_cnt); ! 9950: for (i = 0; i < sgp->entry_cnt; i++) { ! 9951: printk(" [%u]: addr %x, bytes %lu\n", ! 9952: i, (unsigned) sgp->sg_list[i].addr, sgp->sg_list[i].bytes); ! 9953: } ! 9954: ! 9955: } ! 9956: } ! 9957: ! 9958: /* ! 9959: * asc_prt_asc_qdone_info() ! 9960: */ ! 9961: STATIC void ! 9962: asc_prt_asc_qdone_info(ASC_QDONE_INFO *q) ! 9963: { ! 9964: printk("ASC_QDONE_INFO at addr %x\n", (unsigned) q); ! 9965: printk( ! 9966: " srb_ptr %x, target_ix %u, cdb_len %u, tag_code %u, done_stat %x\n", ! 9967: (unsigned) q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len, ! 9968: q->d2.tag_code, q->d3.done_stat); ! 9969: printk( ! 9970: " host_stat %x, scsi_stat %x, scsi_msg %x\n", ! 9971: q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg); ! 9972: } ! 9973: ! 9974: /* ! 9975: * asc_prt_adv_dvc_var() ! 9976: * ! 9977: * Display an ADV_DVC_VAR structure. ! 9978: */ ! 9979: STATIC void ! 9980: asc_prt_adv_dvc_var(ADV_DVC_VAR *h) ! 9981: { ! 9982: printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong) h); ! 9983: ! 9984: printk( ! 9985: " iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n", ! 9986: (ulong) h->iop_base, h->err_code, (unsigned) h->ultra_able); ! 9987: ! 9988: printk( ! 9989: " isr_callback 0x%x, sdtr_able 0x%x, wdtr_able 0x%x\n", ! 9990: (unsigned) h->isr_callback, (unsigned) h->wdtr_able, ! 9991: (unsigned) h->sdtr_able); ! 9992: ! 9993: printk( ! 9994: " start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n", ! 9995: (unsigned) h->start_motor, ! 9996: (unsigned) h->scsi_reset_wait, (unsigned) h->irq_no); ! 9997: ! 9998: printk( ! 9999: " max_host_qng 0x%x, cur_host_qng 0x%x, max_dvc_qng 0x%x\n", ! 10000: (unsigned) h->max_host_qng, (unsigned) h->cur_host_qng, ! 10001: (unsigned) h->max_dvc_qng); ! 10002: ! 10003: printk( ! 10004: " no_scam 0x%x, tagqng_able 0x%x, chip_scsi_id 0x%x, cfg 0x%lx\n", ! 10005: (unsigned) h->no_scam, (unsigned) h->tagqng_able, ! 10006: (unsigned) h->chip_scsi_id, (ulong) h->cfg); ! 10007: ! 10008: } ! 10009: ! 10010: /* ! 10011: * asc_prt_adv_dvc_cfg() ! 10012: * ! 10013: * Display an ADV_DVC_CFG structure. ! 10014: */ ! 10015: STATIC void ! 10016: asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h) ! 10017: { ! 10018: printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong) h); ! 10019: ! 10020: printk( ! 10021: " disc_enable 0x%x, termination 0x%x\n", ! 10022: h->disc_enable, h->termination); ! 10023: ! 10024: printk( ! 10025: " chip_version 0x%x, mcode_date 0x%x\n", ! 10026: h->chip_version, h->mcode_date); ! 10027: ! 10028: printk( ! 10029: " mcode_version 0x%x, pci_device_id 0x%x, lib_version 0x%x\n", ! 10030: h->mcode_version, h->pci_device_id, h->lib_version); ! 10031: ! 10032: printk( ! 10033: " control_flag 0x%x, pci_slot_info 0x%x\n", ! 10034: h->control_flag, h->pci_slot_info); ! 10035: } ! 10036: ! 10037: /* ! 10038: * asc_prt_adv_scsi_req_q() ! 10039: * ! 10040: * Display an ADV_SCSI_REQ_Q structure. ! 10041: */ ! 10042: STATIC void ! 10043: asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q) ! 10044: { ! 10045: int i; ! 10046: struct asc_sg_block *sg_ptr; ! 10047: ! 10048: printk("ADV_SCSI_REQ_Q at addr %x\n", (unsigned) q); ! 10049: ! 10050: printk( ! 10051: " target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n", ! 10052: q->target_id, q->target_lun, q->srb_ptr, q->a_flag); ! 10053: ! 10054: printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n", ! 10055: q->cntl, q->data_addr, q->vdata_addr); ! 10056: ! 10057: printk( ! 10058: " data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", ! 10059: q->data_cnt, q->sense_addr, q->sense_len); ! 10060: ! 10061: printk( ! 10062: " cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n", ! 10063: q->cdb_len, q->done_status, q->host_status, q->scsi_status); ! 10064: ! 10065: printk( ! 10066: " vsense_addr 0x%lx, scsiq_ptr 0x%lx, ux_wk_data_cnt %lu\n", ! 10067: (ulong) q->vsense_addr, (ulong) q->scsiq_ptr, ! 10068: (ulong) q->ux_wk_data_cnt); ! 10069: ! 10070: printk( ! 10071: " sg_list_ptr 0x%lx, sg_real_addr 0x%lx, sg_entry_cnt %u\n", ! 10072: (ulong) q->sg_list_ptr, (ulong) q->sg_real_addr, q->sg_entry_cnt); ! 10073: ! 10074: printk( ! 10075: " ux_sg_ix %u, orig_sense_len %u\n", ! 10076: q->ux_sg_ix, q->orig_sense_len); ! 10077: ! 10078: /* Display the request's ADV_SG_BLOCK structures. */ ! 10079: for (sg_ptr = q->sg_list_ptr, i = 0; sg_ptr != NULL; ! 10080: sg_ptr = sg_ptr->sg_ptr, i++) { ! 10081: /* ! 10082: * 'sg_ptr' is a physical address. Convert it to a virtual ! 10083: * address by indexing 'i' into the virtual address array ! 10084: * 'sg_list_ptr'. ! 10085: * ! 10086: * At the end of the each iteration of the loop 'sg_ptr' is ! 10087: * converted back into a physical address by setting 'sg_ptr' ! 10088: * to the next pointer 'sg_ptr->sg_ptr'. ! 10089: */ ! 10090: sg_ptr = &(((ADV_SG_BLOCK *) (q->sg_list_ptr))[i]); ! 10091: asc_prt_adv_sgblock(i, sg_ptr); ! 10092: } ! 10093: } ! 10094: ! 10095: /* ! 10096: * asc_prt_adv_sgblock() ! 10097: * ! 10098: * Display an ADV_SG_BLOCK structure. ! 10099: */ ! 10100: STATIC void ! 10101: asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b) ! 10102: { ! 10103: int i, s; ! 10104: ! 10105: /* Calculate starting entry number for the current block. */ ! 10106: s = sgblockno * NO_OF_SG_PER_BLOCK; ! 10107: ! 10108: printk(" ADV_SG_BLOCK at addr 0x%lx (sgblockno %lu)\n", ! 10109: (ulong) b, (ulong) sgblockno); ! 10110: printk( ! 10111: " first_entry_no %lu, last_entry_no %lu, sg_ptr 0x%lx\n", ! 10112: (ulong) b->first_entry_no, (ulong) b->last_entry_no, (ulong) b->sg_ptr); ! 10113: ASC_ASSERT(b->first_entry_no - s >= 0); ! 10114: ASC_ASSERT(b->last_entry_no - s >= 0); ! 10115: ASC_ASSERT(b->last_entry_no - s <= NO_OF_SG_PER_BLOCK); ! 10116: ASC_ASSERT(b->first_entry_no - s <= NO_OF_SG_PER_BLOCK); ! 10117: ASC_ASSERT(b->first_entry_no - s <= NO_OF_SG_PER_BLOCK); ! 10118: ASC_ASSERT(b->first_entry_no - s <= b->last_entry_no - s); ! 10119: for (i = b->first_entry_no - s; i <= b->last_entry_no - s; i++) { ! 10120: printk(" [%lu]: sg_addr 0x%lx, sg_count 0x%lx\n", ! 10121: (ulong) i, (ulong) b->sg_list[i].sg_addr, ! 10122: (ulong) b->sg_list[i].sg_count); ! 10123: } ! 10124: } ! 10125: ! 10126: /* ! 10127: * asc_prt_hex() ! 10128: * ! 10129: * Print hexadecimal output in 4 byte groupings 32 bytes ! 10130: * or 8 double-words per line. ! 10131: */ ! 10132: STATIC void ! 10133: asc_prt_hex(char *f, uchar *s, int l) ! 10134: { ! 10135: int i; ! 10136: int j; ! 10137: int k; ! 10138: int m; ! 10139: ! 10140: printk("%s: (%d bytes)\n", f, l); ! 10141: ! 10142: for (i = 0; i < l; i += 32) { ! 10143: ! 10144: /* Display a maximum of 8 double-words per line. */ ! 10145: if ((k = (l - i) / 4) >= 8) { ! 10146: k = 8; ! 10147: m = 0; ! 10148: } else { ! 10149: m = (l - i) % 4 ; ! 10150: } ! 10151: ! 10152: for (j = 0; j < k; j++) { ! 10153: printk(" %2.2X%2.2X%2.2X%2.2X", ! 10154: (unsigned) s[i+(j*4)], (unsigned) s[i+(j*4)+1], ! 10155: (unsigned) s[i+(j*4)+2], (unsigned) s[i+(j*4)+3]); ! 10156: } ! 10157: ! 10158: switch (m) { ! 10159: case 0: ! 10160: default: ! 10161: break; ! 10162: case 1: ! 10163: printk(" %2.2X", ! 10164: (unsigned) s[i+(j*4)]); ! 10165: break; ! 10166: case 2: ! 10167: printk(" %2.2X%2.2X", ! 10168: (unsigned) s[i+(j*4)], ! 10169: (unsigned) s[i+(j*4)+1]); ! 10170: break; ! 10171: case 3: ! 10172: printk(" %2.2X%2.2X%2.2X", ! 10173: (unsigned) s[i+(j*4)+1], ! 10174: (unsigned) s[i+(j*4)+2], ! 10175: (unsigned) s[i+(j*4)+3]); ! 10176: break; ! 10177: } ! 10178: ! 10179: printk("\n"); ! 10180: } ! 10181: } ! 10182: #endif /* ADVANSYS_DEBUG */ ! 10183: ! 10184: #ifdef ADVANSYS_ASSERT ! 10185: /* ! 10186: * interrupts_enabled() ! 10187: * ! 10188: * Return 1 if interrupts are enabled, otherwise return 0. ! 10189: */ ! 10190: STATIC int ! 10191: interrupts_enabled(void) ! 10192: { ! 10193: int flags; ! 10194: ! 10195: save_flags(flags); ! 10196: if (flags & 0x0200) { ! 10197: return ASC_TRUE; ! 10198: } else { ! 10199: return ASC_FALSE; ! 10200: } ! 10201: } ! 10202: #endif /* ADVANSYS_ASSERT */ ! 10203: ! 10204: ! 10205: /* ! 10206: * --- Asc Library Functions ! 10207: */ ! 10208: ! 10209: ASC_INITFUNC( ! 10210: STATIC ushort ! 10211: AscGetEisaChipCfg( ! 10212: PortAddr iop_base ! 10213: ) ! 10214: ) ! 10215: { ! 10216: PortAddr eisa_cfg_iop; ! 10217: ! 10218: eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | ! 10219: (PortAddr) (ASC_EISA_CFG_IOP_MASK); ! 10220: return (inpw(eisa_cfg_iop)); ! 10221: } ! 10222: ! 10223: ASC_INITFUNC( ! 10224: STATIC uchar ! 10225: AscSetChipScsiID( ! 10226: PortAddr iop_base, ! 10227: uchar new_host_id ! 10228: ) ! 10229: ) ! 10230: { ! 10231: ushort cfg_lsw; ! 10232: ! 10233: if (AscGetChipScsiID(iop_base) == new_host_id) { ! 10234: return (new_host_id); ! 10235: } ! 10236: cfg_lsw = AscGetChipCfgLsw(iop_base); ! 10237: cfg_lsw &= 0xF8FF; ! 10238: cfg_lsw |= (ushort) ((new_host_id & ASC_MAX_TID) << 8); ! 10239: AscSetChipCfgLsw(iop_base, cfg_lsw); ! 10240: return (AscGetChipScsiID(iop_base)); ! 10241: } ! 10242: ! 10243: ASC_INITFUNC( ! 10244: STATIC uchar ! 10245: AscGetChipScsiCtrl( ! 10246: PortAddr iop_base ! 10247: ) ! 10248: ) ! 10249: { ! 10250: uchar sc; ! 10251: ! 10252: AscSetBank(iop_base, 1); ! 10253: sc = inp(iop_base + IOP_REG_SC); ! 10254: AscSetBank(iop_base, 0); ! 10255: return (sc); ! 10256: } ! 10257: ! 10258: ASC_INITFUNC( ! 10259: STATIC uchar ! 10260: AscGetChipVersion( ! 10261: PortAddr iop_base, ! 10262: ushort bus_type ! 10263: ) ! 10264: ) ! 10265: { ! 10266: if ((bus_type & ASC_IS_EISA) != 0) { ! 10267: PortAddr eisa_iop; ! 10268: uchar revision; ! 10269: eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | ! 10270: (PortAddr) ASC_EISA_REV_IOP_MASK; ! 10271: revision = inp(eisa_iop); ! 10272: return ((uchar) ((ASC_CHIP_MIN_VER_EISA - 1) + revision)); ! 10273: } ! 10274: return (AscGetChipVerNo(iop_base)); ! 10275: } ! 10276: ! 10277: ASC_INITFUNC( ! 10278: STATIC ushort ! 10279: AscGetChipBusType( ! 10280: PortAddr iop_base ! 10281: ) ! 10282: ) ! 10283: { ! 10284: ushort chip_ver; ! 10285: ! 10286: chip_ver = AscGetChipVerNo(iop_base); ! 10287: if ( ! 10288: (chip_ver >= ASC_CHIP_MIN_VER_VL) ! 10289: && (chip_ver <= ASC_CHIP_MAX_VER_VL) ! 10290: ) { ! 10291: if ( ! 10292: ((iop_base & 0x0C30) == 0x0C30) ! 10293: || ((iop_base & 0x0C50) == 0x0C50) ! 10294: ) { ! 10295: return (ASC_IS_EISA); ! 10296: } ! 10297: return (ASC_IS_VL); ! 10298: } ! 10299: if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) && ! 10300: (chip_ver <= ASC_CHIP_MAX_VER_ISA)) { ! 10301: if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) { ! 10302: return (ASC_IS_ISAPNP); ! 10303: } ! 10304: return (ASC_IS_ISA); ! 10305: } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) && ! 10306: (chip_ver <= ASC_CHIP_MAX_VER_PCI)) { ! 10307: return (ASC_IS_PCI); ! 10308: } ! 10309: return (0); ! 10310: } ! 10311: ! 10312: ASC_INITFUNC( ! 10313: STATIC ulong ! 10314: AscLoadMicroCode( ! 10315: PortAddr iop_base, ! 10316: ushort s_addr, ! 10317: ushort *mcode_buf, ! 10318: ushort mcode_size ! 10319: ) ! 10320: ) ! 10321: { ! 10322: ulong chksum; ! 10323: ushort mcode_word_size; ! 10324: ushort mcode_chksum; ! 10325: ! 10326: mcode_word_size = (ushort) (mcode_size >> 1); ! 10327: AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size); ! 10328: AscMemWordCopyToLram(iop_base, s_addr, mcode_buf, mcode_word_size); ! 10329: chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size); ! 10330: mcode_chksum = (ushort) AscMemSumLramWord(iop_base, ! 10331: (ushort) ASC_CODE_SEC_BEG, ! 10332: (ushort) ((mcode_size - s_addr - (ushort) ASC_CODE_SEC_BEG) / 2)); ! 10333: AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum); ! 10334: AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size); ! 10335: return (chksum); ! 10336: } ! 10337: ! 10338: ASC_INITFUNC( ! 10339: STATIC int ! 10340: AscFindSignature( ! 10341: PortAddr iop_base ! 10342: ) ! 10343: ) ! 10344: { ! 10345: ushort sig_word; ! 10346: ! 10347: if (AscGetChipSignatureByte(iop_base) == (uchar) ASC_1000_ID1B) { ! 10348: sig_word = AscGetChipSignatureWord(iop_base); ! 10349: if ((sig_word == (ushort) ASC_1000_ID0W) || ! 10350: (sig_word == (ushort) ASC_1000_ID0W_FIX)) { ! 10351: return (1); ! 10352: } ! 10353: } ! 10354: return (0); ! 10355: } ! 10356: ! 10357: STATIC uchar _isa_pnp_inited ASC_INITDATA = 0; ! 10358: STATIC PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] ASC_INITDATA = ! 10359: { ! 10360: 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4, ! 10361: ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8 ! 10362: }; ! 10363: ! 10364: ASC_INITFUNC( ! 10365: STATIC PortAddr ! 10366: AscSearchIOPortAddr( ! 10367: PortAddr iop_beg, ! 10368: ushort bus_type ! 10369: ) ! 10370: ) ! 10371: { ! 10372: if (bus_type & ASC_IS_VL) { ! 10373: while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { ! 10374: if (AscGetChipVersion(iop_beg, bus_type) <= ASC_CHIP_MAX_VER_VL) { ! 10375: return (iop_beg); ! 10376: } ! 10377: } ! 10378: return (0); ! 10379: } ! 10380: if (bus_type & ASC_IS_ISA) { ! 10381: if (_isa_pnp_inited == 0) { ! 10382: AscSetISAPNPWaitForKey(); ! 10383: _isa_pnp_inited++; ! 10384: } ! 10385: while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { ! 10386: if ((AscGetChipVersion(iop_beg, bus_type) & ASC_CHIP_VER_ISA_BIT) != 0) { ! 10387: return (iop_beg); ! 10388: } ! 10389: } ! 10390: return (0); ! 10391: } ! 10392: if (bus_type & ASC_IS_EISA) { ! 10393: if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) { ! 10394: return (iop_beg); ! 10395: } ! 10396: return (0); ! 10397: } ! 10398: return (0); ! 10399: } ! 10400: ! 10401: ASC_INITFUNC( ! 10402: STATIC PortAddr ! 10403: AscSearchIOPortAddr11( ! 10404: PortAddr s_addr ! 10405: ) ! 10406: ) ! 10407: { ! 10408: int i; ! 10409: PortAddr iop_base; ! 10410: ! 10411: for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) { ! 10412: if (_asc_def_iop_base[i] > s_addr) { ! 10413: break; ! 10414: } ! 10415: } ! 10416: for (; i < ASC_IOADR_TABLE_MAX_IX; i++) { ! 10417: iop_base = _asc_def_iop_base[i]; ! 10418: if (check_region(iop_base, ASC_IOADR_GAP) != 0) { ! 10419: ASC_DBG1(1, ! 10420: "AscSearchIOPortAddr11: check_region() failed I/O port %x\n", ! 10421: iop_base); ! 10422: continue; ! 10423: } ! 10424: ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port %x\n", iop_base); ! 10425: if (AscFindSignature(iop_base)) { ! 10426: return (iop_base); ! 10427: } ! 10428: } ! 10429: return (0); ! 10430: } ! 10431: ! 10432: ASC_INITFUNC( ! 10433: STATIC void ! 10434: AscToggleIRQAct( ! 10435: PortAddr iop_base ! 10436: ) ! 10437: ) ! 10438: { ! 10439: AscSetChipStatus(iop_base, CIW_IRQ_ACT); ! 10440: AscSetChipStatus(iop_base, 0); ! 10441: return; ! 10442: } ! 10443: ! 10444: ASC_INITFUNC( ! 10445: STATIC void ! 10446: AscSetISAPNPWaitForKey( ! 10447: void) ! 10448: ) ! 10449: { ! 10450: outp(ASC_ISA_PNP_PORT_ADDR, 0x02); ! 10451: outp(ASC_ISA_PNP_PORT_WRITE, 0x02); ! 10452: return; ! 10453: } ! 10454: ! 10455: ASC_INITFUNC( ! 10456: STATIC uchar ! 10457: AscGetChipIRQ( ! 10458: PortAddr iop_base, ! 10459: ushort bus_type ! 10460: ) ! 10461: ) ! 10462: { ! 10463: ushort cfg_lsw; ! 10464: uchar chip_irq; ! 10465: ! 10466: if ((bus_type & ASC_IS_EISA) != 0) { ! 10467: cfg_lsw = AscGetEisaChipCfg(iop_base); ! 10468: chip_irq = (uchar) (((cfg_lsw >> 8) & 0x07) + 10); ! 10469: if ((chip_irq == 13) || (chip_irq > 15)) { ! 10470: return (0); ! 10471: } ! 10472: return (chip_irq); ! 10473: } ! 10474: if ((bus_type & ASC_IS_VL) != 0) { ! 10475: cfg_lsw = AscGetChipCfgLsw(iop_base); ! 10476: chip_irq = (uchar) (((cfg_lsw >> 2) & 0x07)); ! 10477: if ((chip_irq == 0) || ! 10478: (chip_irq == 4) || ! 10479: (chip_irq == 7)) { ! 10480: return (0); ! 10481: } ! 10482: return ((uchar) (chip_irq + (ASC_MIN_IRQ_NO - 1))); ! 10483: } ! 10484: cfg_lsw = AscGetChipCfgLsw(iop_base); ! 10485: chip_irq = (uchar) (((cfg_lsw >> 2) & 0x03)); ! 10486: if (chip_irq == 3) ! 10487: chip_irq += (uchar) 2; ! 10488: return ((uchar) (chip_irq + ASC_MIN_IRQ_NO)); ! 10489: } ! 10490: ! 10491: ASC_INITFUNC( ! 10492: STATIC uchar ! 10493: AscSetChipIRQ( ! 10494: PortAddr iop_base, ! 10495: uchar irq_no, ! 10496: ushort bus_type ! 10497: ) ! 10498: ) ! 10499: { ! 10500: ushort cfg_lsw; ! 10501: ! 10502: if ((bus_type & ASC_IS_VL) != 0) { ! 10503: if (irq_no != 0) { ! 10504: if ((irq_no < ASC_MIN_IRQ_NO) || (irq_no > ASC_MAX_IRQ_NO)) { ! 10505: irq_no = 0; ! 10506: } else { ! 10507: irq_no -= (uchar) ((ASC_MIN_IRQ_NO - 1)); ! 10508: } ! 10509: } ! 10510: cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE3); ! 10511: cfg_lsw |= (ushort) 0x0010; ! 10512: AscSetChipCfgLsw(iop_base, cfg_lsw); ! 10513: AscToggleIRQAct(iop_base); ! 10514: cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFE0); ! 10515: cfg_lsw |= (ushort) ((irq_no & 0x07) << 2); ! 10516: AscSetChipCfgLsw(iop_base, cfg_lsw); ! 10517: AscToggleIRQAct(iop_base); ! 10518: return (AscGetChipIRQ(iop_base, bus_type)); ! 10519: } ! 10520: if ((bus_type & (ASC_IS_ISA)) != 0) { ! 10521: if (irq_no == 15) ! 10522: irq_no -= (uchar) 2; ! 10523: irq_no -= (uchar) ASC_MIN_IRQ_NO; ! 10524: cfg_lsw = (ushort) (AscGetChipCfgLsw(iop_base) & 0xFFF3); ! 10525: cfg_lsw |= (ushort) ((irq_no & 0x03) << 2); ! 10526: AscSetChipCfgLsw(iop_base, cfg_lsw); ! 10527: return (AscGetChipIRQ(iop_base, bus_type)); ! 10528: } ! 10529: return (0); ! 10530: } ! 10531: ! 10532: ASC_INITFUNC( ! 10533: STATIC void ! 10534: AscEnableIsaDma( ! 10535: uchar dma_channel ! 10536: ) ! 10537: ) ! 10538: { ! 10539: if (dma_channel < 4) { ! 10540: outp(0x000B, (ushort) (0xC0 | dma_channel)); ! 10541: outp(0x000A, dma_channel); ! 10542: } else if (dma_channel < 8) { ! 10543: outp(0x00D6, (ushort) (0xC0 | (dma_channel - 4))); ! 10544: outp(0x00D4, (ushort) (dma_channel - 4)); ! 10545: } ! 10546: return; ! 10547: } ! 10548: ! 10549: STATIC int ! 10550: AscIsrChipHalted( ! 10551: REG ASC_DVC_VAR asc_ptr_type * asc_dvc ! 10552: ) ! 10553: { ! 10554: EXT_MSG ext_msg; ! 10555: EXT_MSG out_msg; ! 10556: ushort halt_q_addr; ! 10557: int sdtr_accept; ! 10558: ushort int_halt_code; ! 10559: ASC_SCSI_BIT_ID_TYPE scsi_busy; ! 10560: ASC_SCSI_BIT_ID_TYPE target_id; ! 10561: PortAddr iop_base; ! 10562: uchar tag_code; ! 10563: uchar q_status; ! 10564: uchar halt_qp; ! 10565: uchar sdtr_data; ! 10566: uchar target_ix; ! 10567: uchar q_cntl, tid_no; ! 10568: uchar cur_dvc_qng; ! 10569: uchar asyn_sdtr; ! 10570: uchar scsi_status; ! 10571: asc_board_t *boardp; ! 10572: ! 10573: ASC_ASSERT(asc_dvc->drv_ptr != 0); ! 10574: boardp = (asc_board_t *) asc_dvc->drv_ptr; ! 10575: ! 10576: iop_base = asc_dvc->iop_base; ! 10577: int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W); ! 10578: ! 10579: halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B); ! 10580: halt_q_addr = ASC_QNO_TO_QADDR(halt_qp); ! 10581: target_ix = AscReadLramByte(iop_base, ! 10582: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TARGET_IX)); ! 10583: q_cntl = AscReadLramByte(iop_base, ! 10584: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL)); ! 10585: tid_no = ASC_TIX_TO_TID(target_ix); ! 10586: target_id = (uchar) ASC_TID_TO_TARGET_ID(tid_no); ! 10587: if (asc_dvc->pci_fix_asyn_xfer & target_id) { ! 10588: ! 10589: asyn_sdtr = ASYN_SDTR_DATA_FIX_PCI_REV_AB; ! 10590: } else { ! 10591: asyn_sdtr = 0; ! 10592: } ! 10593: if (int_halt_code == ASC_HALT_DISABLE_ASYN_USE_SYN_FIX) { ! 10594: if (asc_dvc->pci_fix_asyn_xfer & target_id) { ! 10595: AscSetChipSDTR(iop_base, 0, tid_no); ! 10596: boardp->sdtr_data[tid_no] = 0; ! 10597: } ! 10598: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); ! 10599: return (0); ! 10600: } else if (int_halt_code == ASC_HALT_ENABLE_ASYN_USE_SYN_FIX) { ! 10601: if (asc_dvc->pci_fix_asyn_xfer & target_id) { ! 10602: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); ! 10603: boardp->sdtr_data[tid_no] = asyn_sdtr; ! 10604: } ! 10605: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); ! 10606: return (0); ! 10607: } else if (int_halt_code == ASC_HALT_EXTMSG_IN) { ! 10608: ! 10609: AscMemWordCopyFromLram(iop_base, ! 10610: ASCV_MSGIN_BEG, ! 10611: (ushort *) & ext_msg, ! 10612: (ushort) (sizeof (EXT_MSG) >> 1)); ! 10613: ! 10614: if (ext_msg.msg_type == MS_EXTEND && ! 10615: ext_msg.msg_req == MS_SDTR_CODE && ! 10616: ext_msg.msg_len == MS_SDTR_LEN) { ! 10617: sdtr_accept = TRUE; ! 10618: if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) { ! 10619: ! 10620: sdtr_accept = FALSE; ! 10621: ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET; ! 10622: } ! 10623: if ((ext_msg.xfer_period < ! 10624: asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index]) || ! 10625: (ext_msg.xfer_period > ! 10626: asc_dvc->sdtr_period_tbl[asc_dvc->max_sdtr_index])) { ! 10627: sdtr_accept = FALSE; ! 10628: ext_msg.xfer_period = ! 10629: asc_dvc->sdtr_period_tbl[asc_dvc->host_init_sdtr_index]; ! 10630: } ! 10631: if (sdtr_accept) { ! 10632: sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period, ! 10633: ext_msg.req_ack_offset); ! 10634: if ((sdtr_data == 0xFF)) { ! 10635: ! 10636: q_cntl |= QC_MSG_OUT; ! 10637: asc_dvc->init_sdtr &= ~target_id; ! 10638: asc_dvc->sdtr_done &= ~target_id; ! 10639: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); ! 10640: boardp->sdtr_data[tid_no] = asyn_sdtr; ! 10641: } ! 10642: } ! 10643: if (ext_msg.req_ack_offset == 0) { ! 10644: ! 10645: q_cntl &= ~QC_MSG_OUT; ! 10646: asc_dvc->init_sdtr &= ~target_id; ! 10647: asc_dvc->sdtr_done &= ~target_id; ! 10648: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); ! 10649: } else { ! 10650: if (sdtr_accept && (q_cntl & QC_MSG_OUT)) { ! 10651: ! 10652: q_cntl &= ~QC_MSG_OUT; ! 10653: asc_dvc->sdtr_done |= target_id; ! 10654: asc_dvc->init_sdtr |= target_id; ! 10655: asc_dvc->pci_fix_asyn_xfer &= ~target_id; ! 10656: sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period, ! 10657: ext_msg.req_ack_offset); ! 10658: AscSetChipSDTR(iop_base, sdtr_data, tid_no); ! 10659: boardp->sdtr_data[tid_no] = sdtr_data; ! 10660: } else { ! 10661: ! 10662: q_cntl |= QC_MSG_OUT; ! 10663: AscMsgOutSDTR(asc_dvc, ! 10664: ext_msg.xfer_period, ! 10665: ext_msg.req_ack_offset); ! 10666: asc_dvc->pci_fix_asyn_xfer &= ~target_id; ! 10667: sdtr_data = AscCalSDTRData(asc_dvc, ext_msg.xfer_period, ! 10668: ext_msg.req_ack_offset); ! 10669: AscSetChipSDTR(iop_base, sdtr_data, tid_no); ! 10670: boardp->sdtr_data[tid_no] = sdtr_data; ! 10671: asc_dvc->sdtr_done |= target_id; ! 10672: asc_dvc->init_sdtr |= target_id; ! 10673: } ! 10674: } ! 10675: ! 10676: AscWriteLramByte(iop_base, ! 10677: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), ! 10678: q_cntl); ! 10679: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); ! 10680: return (0); ! 10681: } else if (ext_msg.msg_type == MS_EXTEND && ! 10682: ext_msg.msg_req == MS_WDTR_CODE && ! 10683: ext_msg.msg_len == MS_WDTR_LEN) { ! 10684: ! 10685: ext_msg.wdtr_width = 0; ! 10686: AscMemWordCopyToLram(iop_base, ! 10687: ASCV_MSGOUT_BEG, ! 10688: (ushort *) & ext_msg, ! 10689: (ushort) (sizeof (EXT_MSG) >> 1)); ! 10690: q_cntl |= QC_MSG_OUT; ! 10691: AscWriteLramByte(iop_base, ! 10692: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), ! 10693: q_cntl); ! 10694: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); ! 10695: return (0); ! 10696: } else { ! 10697: ! 10698: ext_msg.msg_type = M1_MSG_REJECT; ! 10699: AscMemWordCopyToLram(iop_base, ! 10700: ASCV_MSGOUT_BEG, ! 10701: (ushort *) & ext_msg, ! 10702: (ushort) (sizeof (EXT_MSG) >> 1)); ! 10703: q_cntl |= QC_MSG_OUT; ! 10704: AscWriteLramByte(iop_base, ! 10705: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), ! 10706: q_cntl); ! 10707: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); ! 10708: return (0); ! 10709: } ! 10710: } else if (int_halt_code == ASC_HALT_CHK_CONDITION) { ! 10711: ! 10712: q_cntl |= QC_REQ_SENSE; ! 10713: ! 10714: if ((asc_dvc->init_sdtr & target_id) != 0) { ! 10715: ! 10716: asc_dvc->sdtr_done &= ~target_id; ! 10717: ! 10718: sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); ! 10719: q_cntl |= QC_MSG_OUT; ! 10720: AscMsgOutSDTR(asc_dvc, ! 10721: asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) & ! 10722: (uchar) (asc_dvc->max_sdtr_index - 1)], ! 10723: (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET)); ! 10724: } ! 10725: ! 10726: AscWriteLramByte(iop_base, ! 10727: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), ! 10728: q_cntl); ! 10729: ! 10730: tag_code = AscReadLramByte(iop_base, ! 10731: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE)); ! 10732: tag_code &= 0xDC; ! 10733: if ( ! 10734: (asc_dvc->pci_fix_asyn_xfer & target_id) ! 10735: && !(asc_dvc->pci_fix_asyn_xfer_always & target_id) ! 10736: ) { ! 10737: ! 10738: tag_code |= (ASC_TAG_FLAG_DISABLE_DISCONNECT ! 10739: | ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX); ! 10740: ! 10741: } ! 10742: AscWriteLramByte(iop_base, ! 10743: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_TAG_CODE), ! 10744: tag_code); ! 10745: ! 10746: q_status = AscReadLramByte(iop_base, ! 10747: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS)); ! 10748: q_status |= (QS_READY | QS_BUSY); ! 10749: AscWriteLramByte(iop_base, ! 10750: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_STATUS), ! 10751: q_status); ! 10752: ! 10753: scsi_busy = AscReadLramByte(iop_base, ! 10754: (ushort) ASCV_SCSIBUSY_B); ! 10755: scsi_busy &= ~target_id; ! 10756: AscWriteLramByte(iop_base, (ushort) ASCV_SCSIBUSY_B, scsi_busy); ! 10757: ! 10758: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); ! 10759: return (0); ! 10760: } else if (int_halt_code == ASC_HALT_SDTR_REJECTED) { ! 10761: ! 10762: AscMemWordCopyFromLram(iop_base, ! 10763: ASCV_MSGOUT_BEG, ! 10764: (ushort *) & out_msg, ! 10765: (ushort) (sizeof (EXT_MSG) >> 1)); ! 10766: ! 10767: if ((out_msg.msg_type == MS_EXTEND) && ! 10768: (out_msg.msg_len == MS_SDTR_LEN) && ! 10769: (out_msg.msg_req == MS_SDTR_CODE)) { ! 10770: ! 10771: asc_dvc->init_sdtr &= ~target_id; ! 10772: asc_dvc->sdtr_done &= ~target_id; ! 10773: AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); ! 10774: boardp->sdtr_data[tid_no] = asyn_sdtr; ! 10775: } ! 10776: q_cntl &= ~QC_MSG_OUT; ! 10777: AscWriteLramByte(iop_base, ! 10778: (ushort) (halt_q_addr + (ushort) ASC_SCSIQ_B_CNTL), ! 10779: q_cntl); ! 10780: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); ! 10781: return (0); ! 10782: } else if (int_halt_code == ASC_HALT_SS_QUEUE_FULL) { ! 10783: ! 10784: scsi_status = AscReadLramByte(iop_base, ! 10785: (ushort) ((ushort) halt_q_addr + (ushort) ASC_SCSIQ_SCSI_STATUS)); ! 10786: cur_dvc_qng = AscReadLramByte(iop_base, ! 10787: (ushort) ((ushort) ASC_QADR_BEG + (ushort) target_ix)); ! 10788: if ((cur_dvc_qng > 0) && ! 10789: (asc_dvc->cur_dvc_qng[tid_no] > 0)) { ! 10790: ! 10791: scsi_busy = AscReadLramByte(iop_base, ! 10792: (ushort) ASCV_SCSIBUSY_B); ! 10793: scsi_busy |= target_id; ! 10794: AscWriteLramByte(iop_base, ! 10795: (ushort) ASCV_SCSIBUSY_B, scsi_busy); ! 10796: asc_dvc->queue_full_or_busy |= target_id; ! 10797: ! 10798: if (scsi_status == SS_QUEUE_FULL) { ! 10799: if (cur_dvc_qng > ASC_MIN_TAGGED_CMD) { ! 10800: cur_dvc_qng -= 1; ! 10801: asc_dvc->max_dvc_qng[tid_no] = cur_dvc_qng; ! 10802: ! 10803: AscWriteLramByte(iop_base, ! 10804: (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + ! 10805: (ushort) tid_no), ! 10806: cur_dvc_qng); ! 10807: ! 10808: /* ! 10809: * Set the device queue depth to the number of ! 10810: * active requests when the QUEUE FULL condition ! 10811: * was encountered. ! 10812: */ ! 10813: boardp->queue_full |= target_id; ! 10814: boardp->queue_full_cnt[tid_no] = cur_dvc_qng; ! 10815: #if ASC_QUEUE_FLOW_CONTROL ! 10816: if (boardp->device[tid_no] != NULL && ! 10817: boardp->device[tid_no]->queue_curr_depth > ! 10818: cur_dvc_qng) { ! 10819: boardp->device[tid_no]->queue_curr_depth = ! 10820: cur_dvc_qng; ! 10821: } ! 10822: #endif /* ASC_QUEUE_FLOW_CONTROL */ ! 10823: } ! 10824: } ! 10825: } ! 10826: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); ! 10827: return (0); ! 10828: } ! 10829: return (0); ! 10830: } ! 10831: ! 10832: STATIC uchar ! 10833: _AscCopyLramScsiDoneQ( ! 10834: PortAddr iop_base, ! 10835: ushort q_addr, ! 10836: REG ASC_QDONE_INFO * scsiq, ! 10837: ulong max_dma_count ! 10838: ) ! 10839: { ! 10840: ushort _val; ! 10841: uchar sg_queue_cnt; ! 10842: ! 10843: DvcGetQinfo(iop_base, ! 10844: (ushort) (q_addr + (ushort) ASC_SCSIQ_DONE_INFO_BEG), ! 10845: (ushort *) scsiq, ! 10846: (ushort) ((sizeof (ASC_SCSIQ_2) + sizeof (ASC_SCSIQ_3)) / 2)); ! 10847: _val = AscReadLramWord(iop_base, ! 10848: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS)); ! 10849: scsiq->q_status = (uchar) _val; ! 10850: scsiq->q_no = (uchar) (_val >> 8); ! 10851: _val = AscReadLramWord(iop_base, ! 10852: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_CNTL)); ! 10853: scsiq->cntl = (uchar) _val; ! 10854: sg_queue_cnt = (uchar) (_val >> 8); ! 10855: _val = AscReadLramWord(iop_base, ! 10856: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_SENSE_LEN)); ! 10857: scsiq->sense_len = (uchar) _val; ! 10858: scsiq->extra_bytes = (uchar) (_val >> 8); ! 10859: scsiq->remain_bytes = AscReadLramWord(iop_base, ! 10860: (ushort) (q_addr + (ushort) ASC_SCSIQ_DW_REMAIN_XFER_CNT)); ! 10861: scsiq->remain_bytes &= max_dma_count; ! 10862: return (sg_queue_cnt); ! 10863: } ! 10864: ! 10865: STATIC int ! 10866: AscIsrQDone( ! 10867: REG ASC_DVC_VAR asc_ptr_type * asc_dvc ! 10868: ) ! 10869: { ! 10870: uchar next_qp; ! 10871: uchar n_q_used; ! 10872: uchar sg_list_qp; ! 10873: uchar sg_queue_cnt; ! 10874: uchar q_cnt; ! 10875: uchar done_q_tail; ! 10876: uchar tid_no; ! 10877: ASC_SCSI_BIT_ID_TYPE scsi_busy; ! 10878: ASC_SCSI_BIT_ID_TYPE target_id; ! 10879: PortAddr iop_base; ! 10880: ushort q_addr; ! 10881: ushort sg_q_addr; ! 10882: uchar cur_target_qng; ! 10883: ASC_QDONE_INFO scsiq_buf; ! 10884: REG ASC_QDONE_INFO *scsiq; ! 10885: int false_overrun; ! 10886: ASC_ISR_CALLBACK asc_isr_callback; ! 10887: ! 10888: iop_base = asc_dvc->iop_base; ! 10889: asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback; ! 10890: n_q_used = 1; ! 10891: scsiq = (ASC_QDONE_INFO *) & scsiq_buf; ! 10892: done_q_tail = (uchar) AscGetVarDoneQTail(iop_base); ! 10893: q_addr = ASC_QNO_TO_QADDR(done_q_tail); ! 10894: next_qp = AscReadLramByte(iop_base, ! 10895: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_FWD)); ! 10896: if (next_qp != ASC_QLINK_END) { ! 10897: AscPutVarDoneQTail(iop_base, next_qp); ! 10898: q_addr = ASC_QNO_TO_QADDR(next_qp); ! 10899: sg_queue_cnt = _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, ! 10900: asc_dvc->max_dma_count); ! 10901: AscWriteLramByte(iop_base, ! 10902: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), ! 10903: (uchar) (scsiq->q_status & (uchar) ~ (QS_READY | QS_ABORTED))); ! 10904: tid_no = ASC_TIX_TO_TID(scsiq->d2.target_ix); ! 10905: target_id = ASC_TIX_TO_TARGET_ID(scsiq->d2.target_ix); ! 10906: if ((scsiq->cntl & QC_SG_HEAD) != 0) { ! 10907: sg_q_addr = q_addr; ! 10908: sg_list_qp = next_qp; ! 10909: for (q_cnt = 0; q_cnt < sg_queue_cnt; q_cnt++) { ! 10910: sg_list_qp = AscReadLramByte(iop_base, ! 10911: (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_FWD)); ! 10912: sg_q_addr = ASC_QNO_TO_QADDR(sg_list_qp); ! 10913: if (sg_list_qp == ASC_QLINK_END) { ! 10914: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SG_Q_LINKS); ! 10915: scsiq->d3.done_stat = QD_WITH_ERROR; ! 10916: scsiq->d3.host_stat = QHSTA_D_QDONE_SG_LIST_CORRUPTED; ! 10917: goto FATAL_ERR_QDONE; ! 10918: } ! 10919: AscWriteLramByte(iop_base, ! 10920: (ushort) (sg_q_addr + (ushort) ASC_SCSIQ_B_STATUS), ! 10921: QS_FREE); ! 10922: } ! 10923: n_q_used = sg_queue_cnt + 1; ! 10924: AscPutVarDoneQTail(iop_base, sg_list_qp); ! 10925: } ! 10926: if (asc_dvc->queue_full_or_busy & target_id) { ! 10927: cur_target_qng = AscReadLramByte(iop_base, ! 10928: (ushort) ((ushort) ASC_QADR_BEG + (ushort) scsiq->d2.target_ix)); ! 10929: if (cur_target_qng < asc_dvc->max_dvc_qng[tid_no]) { ! 10930: scsi_busy = AscReadLramByte(iop_base, ! 10931: (ushort) ASCV_SCSIBUSY_B); ! 10932: scsi_busy &= ~target_id; ! 10933: AscWriteLramByte(iop_base, ! 10934: (ushort) ASCV_SCSIBUSY_B, scsi_busy); ! 10935: asc_dvc->queue_full_or_busy &= ~target_id; ! 10936: } ! 10937: } ! 10938: if (asc_dvc->cur_total_qng >= n_q_used) { ! 10939: asc_dvc->cur_total_qng -= n_q_used; ! 10940: if (asc_dvc->cur_dvc_qng[tid_no] != 0) { ! 10941: asc_dvc->cur_dvc_qng[tid_no]--; ! 10942: } ! 10943: } else { ! 10944: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CUR_QNG); ! 10945: scsiq->d3.done_stat = QD_WITH_ERROR; ! 10946: goto FATAL_ERR_QDONE; ! 10947: } ! 10948: if ((scsiq->d2.srb_ptr == 0UL) || ! 10949: ((scsiq->q_status & QS_ABORTED) != 0)) { ! 10950: return (0x11); ! 10951: } else if (scsiq->q_status == QS_DONE) { ! 10952: false_overrun = FALSE; ! 10953: if (scsiq->extra_bytes != 0) { ! 10954: scsiq->remain_bytes += (ulong) scsiq->extra_bytes; ! 10955: } ! 10956: if (scsiq->d3.done_stat == QD_WITH_ERROR) { ! 10957: if (scsiq->d3.host_stat == QHSTA_M_DATA_OVER_RUN) { ! 10958: if ((scsiq->cntl & (QC_DATA_IN | QC_DATA_OUT)) == 0) { ! 10959: scsiq->d3.done_stat = QD_NO_ERROR; ! 10960: scsiq->d3.host_stat = QHSTA_NO_ERROR; ! 10961: } else if (false_overrun) { ! 10962: scsiq->d3.done_stat = QD_NO_ERROR; ! 10963: scsiq->d3.host_stat = QHSTA_NO_ERROR; ! 10964: } ! 10965: } else if (scsiq->d3.host_stat == ! 10966: QHSTA_M_HUNG_REQ_SCSI_BUS_RESET) { ! 10967: AscStopChip(iop_base); ! 10968: AscSetChipControl(iop_base, ! 10969: (uchar) (CC_SCSI_RESET | CC_HALT)); ! 10970: DvcDelayNanoSecond(asc_dvc, 60000); ! 10971: AscSetChipControl(iop_base, CC_HALT); ! 10972: AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); ! 10973: AscSetChipStatus(iop_base, 0); ! 10974: AscSetChipControl(iop_base, 0); ! 10975: } ! 10976: } ! 10977: if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { ! 10978: (*asc_isr_callback) (asc_dvc, scsiq); ! 10979: } else { ! 10980: if ((AscReadLramByte(iop_base, ! 10981: (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG)) == ! 10982: SCSICMD_StartStopUnit)) { ! 10983: asc_dvc->unit_not_ready &= ~target_id; ! 10984: if (scsiq->d3.done_stat != QD_NO_ERROR) { ! 10985: asc_dvc->start_motor &= ~target_id; ! 10986: } ! 10987: } ! 10988: } ! 10989: return (1); ! 10990: } else { ! 10991: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS); ! 10992: FATAL_ERR_QDONE: ! 10993: if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { ! 10994: (*asc_isr_callback) (asc_dvc, scsiq); ! 10995: } ! 10996: return (0x80); ! 10997: } ! 10998: } ! 10999: return (0); ! 11000: } ! 11001: ! 11002: STATIC int ! 11003: AscISR( ! 11004: REG ASC_DVC_VAR asc_ptr_type * asc_dvc ! 11005: ) ! 11006: { ! 11007: ASC_CS_TYPE chipstat; ! 11008: PortAddr iop_base; ! 11009: ushort saved_ram_addr; ! 11010: uchar ctrl_reg; ! 11011: uchar saved_ctrl_reg; ! 11012: int int_pending; ! 11013: int status; ! 11014: uchar host_flag; ! 11015: ! 11016: iop_base = asc_dvc->iop_base; ! 11017: int_pending = FALSE; ! 11018: if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) ! 11019: || (asc_dvc->isr_callback == 0) ! 11020: ) { ! 11021: return (ERR); ! 11022: } ! 11023: if (asc_dvc->in_critical_cnt != 0) { ! 11024: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL); ! 11025: return (ERR); ! 11026: } ! 11027: if (asc_dvc->is_in_int) { ! 11028: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY); ! 11029: return (ERR); ! 11030: } ! 11031: asc_dvc->is_in_int = TRUE; ! 11032: ctrl_reg = AscGetChipControl(iop_base); ! 11033: saved_ctrl_reg = ctrl_reg & (~(CC_SCSI_RESET | CC_CHIP_RESET | ! 11034: CC_SINGLE_STEP | CC_DIAG | CC_TEST)); ! 11035: chipstat = AscGetChipStatus(iop_base); ! 11036: if (chipstat & CSW_SCSI_RESET_LATCH) { ! 11037: if (!(asc_dvc->bus_type & (ASC_IS_VL | ASC_IS_EISA))) { ! 11038: int_pending = TRUE; ! 11039: asc_dvc->sdtr_done = 0; ! 11040: saved_ctrl_reg &= (uchar) (~CC_HALT); ! 11041: while (AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) ; ! 11042: AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT)); ! 11043: AscSetChipControl(iop_base, CC_HALT); ! 11044: AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); ! 11045: AscSetChipStatus(iop_base, 0); ! 11046: chipstat = AscGetChipStatus(iop_base); ! 11047: } ! 11048: } ! 11049: saved_ram_addr = AscGetChipLramAddr(iop_base); ! 11050: host_flag = AscReadLramByte(iop_base, ! 11051: ASCV_HOST_FLAG_B) & (uchar) (~ASC_HOST_FLAG_IN_ISR); ! 11052: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, ! 11053: (uchar) (host_flag | (uchar) ASC_HOST_FLAG_IN_ISR)); ! 11054: if ((chipstat & CSW_INT_PENDING) ! 11055: || (int_pending) ! 11056: ) { ! 11057: AscAckInterrupt(iop_base); ! 11058: int_pending = TRUE; ! 11059: if ((chipstat & CSW_HALTED) && ! 11060: (ctrl_reg & CC_SINGLE_STEP)) { ! 11061: if (AscIsrChipHalted(asc_dvc) == ERR) { ! 11062: goto ISR_REPORT_QDONE_FATAL_ERROR; ! 11063: } else { ! 11064: saved_ctrl_reg &= (uchar) (~CC_HALT); ! 11065: } ! 11066: } else { ! 11067: ISR_REPORT_QDONE_FATAL_ERROR: ! 11068: if ((asc_dvc->dvc_cntl & ASC_CNTL_INT_MULTI_Q) != 0) { ! 11069: while (((status = AscIsrQDone(asc_dvc)) & 0x01) != 0) { ! 11070: } ! 11071: } else { ! 11072: do { ! 11073: if ((status = AscIsrQDone(asc_dvc)) == 1) { ! 11074: break; ! 11075: } ! 11076: } while (status == 0x11); ! 11077: } ! 11078: if ((status & 0x80) != 0) ! 11079: int_pending = ERR; ! 11080: } ! 11081: } ! 11082: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); ! 11083: AscSetChipLramAddr(iop_base, saved_ram_addr); ! 11084: AscSetChipControl(iop_base, saved_ctrl_reg); ! 11085: asc_dvc->is_in_int = FALSE; ! 11086: return (int_pending); ! 11087: } ! 11088: ! 11089: STATIC uchar _asc_mcode_buf[] ASC_INITDATA = ! 11090: { ! 11091: 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 11092: 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 11093: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 11094: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 11095: 0x00, 0x00, 0x00, 0x00, 0x91, 0x10, 0x0A, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, ! 11096: 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 11097: 0x00, 0x00, 0x00, 0x23, 0x00, 0x24, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, ! 11098: 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE2, 0x88, 0x00, 0x00, 0x00, 0x00, ! 11099: 0x80, 0x73, 0x48, 0x04, 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40, ! 11100: 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2, 0xC2, 0x00, 0x92, 0x80, ! 11101: 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, ! 11102: 0x4F, 0x00, 0xF5, 0x00, 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62, ! 11103: 0x92, 0x80, 0x00, 0x46, 0x17, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8, 0xCD, 0x04, 0x4D, 0x00, ! 11104: 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, ! 11105: 0x80, 0x73, 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xE2, 0x01, 0xA6, 0x97, 0xCE, 0x81, 0x00, 0x33, ! 11106: 0x02, 0x00, 0xC0, 0x88, 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0x02, 0x01, 0x4F, 0x00, ! 11107: 0x84, 0x97, 0x07, 0xA6, 0x0C, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x03, 0xDE, ! 11108: 0x00, 0x33, 0x05, 0x00, 0xC0, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00, 0x02, 0x03, 0x4A, 0x60, ! 11109: 0x00, 0xA2, 0x80, 0x01, 0x80, 0x63, 0x07, 0xA6, 0x2C, 0x01, 0x80, 0x81, 0x03, 0x03, 0x80, 0x63, ! 11110: 0xE2, 0x00, 0x07, 0xA6, 0x3C, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC0, 0x88, 0x03, 0x07, 0x02, 0x01, ! 11111: 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8, 0x0D, 0x23, 0x68, 0x98, ! 11112: 0xCD, 0x04, 0x15, 0x23, 0xF6, 0x88, 0xFB, 0x23, 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, ! 11113: 0x06, 0xA3, 0x6A, 0x01, 0x00, 0x33, 0x0A, 0x00, 0xC0, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x76, 0x01, ! 11114: 0x00, 0x33, 0x0B, 0x00, 0xC0, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1A, 0x00, 0xC0, 0x88, ! 11115: 0x50, 0x04, 0x90, 0x81, 0x06, 0xAB, 0x8A, 0x01, 0x90, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x9A, 0x01, ! 11116: 0x50, 0x00, 0x00, 0xA3, 0x44, 0x01, 0x00, 0x05, 0x84, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6, ! 11117: 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xC6, 0x81, 0xFD, 0x23, 0x02, 0x61, 0x82, 0x01, ! 11118: 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xBC, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, ! 11119: 0x00, 0x33, 0x1B, 0x00, 0xC0, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01, ! 11120: 0x00, 0xA2, 0xDC, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xE2, 0x01, 0xE6, 0x84, 0x80, 0x23, 0xA0, 0x01, ! 11121: 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x08, 0x02, 0x04, 0x01, 0x0C, 0xDE, ! 11122: 0x02, 0x01, 0x03, 0xCC, 0x4F, 0x00, 0x84, 0x97, 0x04, 0x82, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01, ! 11123: 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46, 0x56, 0x00, 0x03, 0xC0, ! 11124: 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29, 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x67, 0xEB, ! 11125: 0x11, 0x23, 0xF6, 0x88, 0x04, 0x98, 0xF4, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x32, 0x02, ! 11126: 0x7C, 0x95, 0x06, 0xA6, 0x3C, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0xC0, 0x88, 0x04, 0x01, 0x03, 0xD8, ! 11127: 0xB2, 0x98, 0x6A, 0x96, 0x4E, 0x82, 0xFE, 0x95, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, ! 11128: 0x02, 0xA6, 0x78, 0x02, 0x07, 0xA6, 0x66, 0x02, 0x06, 0xA6, 0x6A, 0x02, 0x03, 0xA6, 0x6E, 0x02, ! 11129: 0x00, 0x33, 0x10, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x50, 0x82, 0x60, 0x96, 0x50, 0x82, 0x04, 0x23, ! 11130: 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC, 0xE0, 0x23, 0x25, 0x61, ! 11131: 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01, 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, ! 11132: 0x06, 0x23, 0x9C, 0x01, 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xB6, 0x02, 0x07, 0xA6, 0x66, 0x02, ! 11133: 0x06, 0xA6, 0x6A, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xC0, 0x02, 0x00, 0xA6, 0xC0, 0x02, ! 11134: 0x00, 0x33, 0x12, 0x00, 0xC0, 0x88, 0x00, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x98, 0x02, ! 11135: 0x4D, 0x04, 0x04, 0x01, 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35, ! 11136: 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xF6, 0x82, 0x18, 0x23, 0x04, 0x61, ! 11137: 0x18, 0xA0, 0xEE, 0x02, 0x04, 0x01, 0x9C, 0xC8, 0x00, 0x33, 0x1F, 0x00, 0xC0, 0x88, 0x08, 0x31, ! 11138: 0x0A, 0x35, 0x0C, 0x39, 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x20, 0x03, 0x00, 0xA6, ! 11139: 0x20, 0x03, 0x07, 0xA6, 0x18, 0x03, 0x06, 0xA6, 0x1C, 0x03, 0x03, 0xA6, 0x20, 0x04, 0x02, 0xA6, ! 11140: 0x78, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0xFA, 0x82, 0x60, 0x96, 0xFA, 0x82, ! 11141: 0x82, 0x98, 0x80, 0x42, 0x7E, 0x98, 0x60, 0xE4, 0x04, 0x01, 0x29, 0xC8, 0x31, 0x05, 0x07, 0x01, ! 11142: 0x00, 0xA2, 0x60, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98, 0x7E, 0x98, 0x00, 0xA6, ! 11143: 0x22, 0x03, 0x07, 0xA6, 0x58, 0x03, 0x03, 0xA6, 0x3C, 0x04, 0x06, 0xA6, 0x5C, 0x03, 0x01, 0xA6, ! 11144: 0x22, 0x03, 0x00, 0x33, 0x25, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x3E, 0x83, 0x60, 0x96, 0x3E, 0x83, ! 11145: 0x04, 0x01, 0x0C, 0xCE, 0x03, 0xC8, 0x00, 0x33, 0x42, 0x00, 0xC0, 0x88, 0x00, 0x01, 0x05, 0x05, ! 11146: 0xFF, 0xA2, 0x7E, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x3A, 0x83, 0x05, 0x05, 0x15, 0x01, ! 11147: 0x00, 0xA2, 0x9E, 0x03, 0xEC, 0x00, 0x6E, 0x00, 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, ! 11148: 0x01, 0xA6, 0x9A, 0x03, 0x00, 0xA6, 0x9A, 0x03, 0x12, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6, ! 11149: 0xA8, 0x03, 0x00, 0xA6, 0xC0, 0x03, 0x12, 0x84, 0xA6, 0x98, 0x80, 0x42, 0x01, 0xA6, 0xA8, 0x03, ! 11150: 0x07, 0xA6, 0xB6, 0x03, 0xD8, 0x83, 0x7C, 0x95, 0xAC, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC0, 0x88, ! 11151: 0xA6, 0x98, 0x80, 0x42, 0x00, 0xA6, 0xC0, 0x03, 0x07, 0xA6, 0xCE, 0x03, 0xD8, 0x83, 0x7C, 0x95, ! 11152: 0xC4, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC0, 0x88, 0x38, 0x2B, 0x80, 0x32, 0x80, 0x36, 0x04, 0x23, ! 11153: 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x12, 0x84, 0x06, 0xF0, 0x06, 0xA4, 0xF6, 0x03, 0x80, 0x6B, ! 11154: 0x05, 0x23, 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x10, 0x04, 0x07, 0xA6, 0x08, 0x04, 0x06, 0xA6, ! 11155: 0x0C, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0xF6, 0x83, 0x60, 0x96, 0xF6, 0x83, ! 11156: 0x20, 0x84, 0x06, 0xF0, 0x06, 0xA4, 0x20, 0x04, 0x80, 0x6B, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63, ! 11157: 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6, 0x38, 0x04, 0x00, 0x33, ! 11158: 0x30, 0x00, 0xC0, 0x88, 0x7C, 0x95, 0x20, 0x84, 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, ! 11159: 0x00, 0x33, 0x00, 0x84, 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63, ! 11160: 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x80, 0x63, 0xA3, 0x01, ! 11161: 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2, 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, ! 11162: 0x00, 0x33, 0x1D, 0x00, 0xC0, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00, ! 11163: 0xC0, 0x88, 0x42, 0x23, 0xF6, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04, 0x08, 0x23, 0x22, 0xA3, ! 11164: 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04, 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, ! 11165: 0xF6, 0x88, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF6, 0x88, 0x04, 0x98, ! 11166: 0x00, 0xA2, 0xC0, 0x04, 0xB2, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20, 0x81, 0x62, 0xF0, 0x81, ! 11167: 0x47, 0x23, 0xF6, 0x88, 0x04, 0x01, 0x0B, 0xDE, 0x04, 0x98, 0xB2, 0x98, 0x00, 0x33, 0x00, 0x81, ! 11168: 0xC0, 0x20, 0x81, 0x62, 0x14, 0x01, 0x00, 0xA0, 0x08, 0x02, 0x43, 0x23, 0xF6, 0x88, 0x04, 0x23, ! 11169: 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3, 0xF4, 0x04, 0x00, 0x33, ! 11170: 0x27, 0x00, 0xC0, 0x88, 0x04, 0x01, 0x04, 0xDC, 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, ! 11171: 0x04, 0x98, 0x26, 0x95, 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05, ! 11172: 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85, 0x46, 0x97, 0xCD, 0x04, ! 11173: 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01, 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, ! 11174: 0x02, 0x23, 0xA0, 0x01, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6, ! 11175: 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x49, 0x00, 0x81, 0x01, ! 11176: 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01, 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, ! 11177: 0xC9, 0x00, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00, ! 11178: 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63, 0x07, 0xA4, 0xF8, 0x05, ! 11179: 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85, 0x00, 0x33, 0x2D, 0x00, 0xC0, 0x88, 0x04, 0xA0, ! 11180: 0xB8, 0x05, 0x80, 0x63, 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05, ! 11181: 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00, 0x62, 0x97, 0x04, 0x85, ! 11182: 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85, 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, ! 11183: 0xC4, 0x05, 0xF4, 0x85, 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0, ! 11184: 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05, 0x80, 0x67, 0x80, 0x63, ! 11185: 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23, 0x68, 0x98, 0x48, 0x23, 0xF6, 0x88, 0x07, 0x23, ! 11186: 0x80, 0x00, 0x06, 0x87, 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00, ! 11187: 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23, 0x07, 0x41, 0x83, 0x03, ! 11188: 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33, 0x37, 0x00, 0xC0, 0x88, 0x1D, 0x01, 0x01, 0xD6, ! 11189: 0x20, 0x23, 0x63, 0x60, 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05, ! 11190: 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00, 0x52, 0x00, 0x06, 0x61, ! 11191: 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA, 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, ! 11192: 0x04, 0xCC, 0x00, 0x33, 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63, ! 11193: 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23, 0xDF, 0x00, 0x06, 0xA6, ! 11194: 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, ! 11195: 0x81, 0x62, 0x00, 0x63, 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06, ! 11196: 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B, 0x40, 0x0E, 0x80, 0x63, ! 11197: 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, ! 11198: 0x00, 0xA0, 0xA2, 0x06, 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E, ! 11199: 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x07, 0xA6, 0xD6, 0x06, ! 11200: 0x00, 0x33, 0x2A, 0x00, 0xC0, 0x88, 0x03, 0x03, 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, ! 11201: 0xE8, 0x06, 0x00, 0x33, 0x29, 0x00, 0xC0, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E, ! 11202: 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20, 0x81, 0x62, 0x04, 0x01, ! 11203: 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, ! 11204: 0x2C, 0x00, 0xC0, 0x88, 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, ! 11205: 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC0, 0x88, 0x00, 0x00, 0x80, 0x67, ! 11206: 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, ! 11207: 0x84, 0x01, 0xE6, 0x84, 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00, ! 11208: 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04, 0x80, 0x05, 0x81, 0x05, ! 11209: 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, ! 11210: 0x70, 0x04, 0x71, 0x00, 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01, ! 11211: 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01, 0xF1, 0x00, 0x70, 0x00, ! 11212: 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01, 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, ! 11213: 0x81, 0x01, 0x70, 0x04, 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01, ! 11214: 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1, 0xC4, 0x07, 0x00, 0x33, ! 11215: 0x07, 0x00, 0xC0, 0x88, 0x80, 0x05, 0x81, 0x05, 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, ! 11216: 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07, ! 11217: 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01, 0x05, 0x05, 0x00, 0x63, ! 11218: 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, ! 11219: 0x77, 0x04, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0, ! 11220: 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63, 0xF3, 0x04, ! 11221: 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43, 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, ! 11222: 0x74, 0x04, 0x02, 0x01, 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98, ! 11223: 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04, 0x5A, 0x88, 0x02, 0x01, ! 11224: 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95, 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, ! 11225: 0x00, 0x05, 0x4E, 0x88, 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08, ! 11226: 0x00, 0x33, 0x3E, 0x00, 0xC0, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x38, 0x2B, ! 11227: 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09, 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, ! 11228: 0x00, 0x63, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36, ! 11229: 0x80, 0x3A, 0x80, 0x3E, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32, 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, ! 11230: 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40, 0x00, 0xA0, 0xB2, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, ! 11231: 0x80, 0x73, 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73, 0x13, 0x23, ! 11232: 0xF6, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01, 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, ! 11233: 0xE0, 0x88, 0x80, 0x73, 0x80, 0x77, 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, ! 11234: 0x41, 0x23, 0xF6, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84, ! 11235: }; ! 11236: ! 11237: STATIC ushort _asc_mcode_size ASC_INITDATA = sizeof(_asc_mcode_buf); ! 11238: STATIC ulong _asc_mcode_chksum ASC_INITDATA = 0x012B5442UL; ! 11239: ! 11240: #define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16 ! 11241: STATIC uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = ! 11242: { ! 11243: SCSICMD_Inquiry, ! 11244: SCSICMD_RequestSense, ! 11245: SCSICMD_ReadCapacity, ! 11246: SCSICMD_ReadTOC, ! 11247: SCSICMD_ModeSelect6, ! 11248: SCSICMD_ModeSense6, ! 11249: SCSICMD_ModeSelect10, ! 11250: SCSICMD_ModeSense10, ! 11251: 0xFF, ! 11252: 0xFF, ! 11253: 0xFF, ! 11254: 0xFF, ! 11255: 0xFF, ! 11256: 0xFF, ! 11257: 0xFF, ! 11258: 0xFF ! 11259: }; ! 11260: ! 11261: STATIC int ! 11262: AscExeScsiQueue( ! 11263: REG ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 11264: REG ASC_SCSI_Q * scsiq ! 11265: ) ! 11266: { ! 11267: PortAddr iop_base; ! 11268: int last_int_level; ! 11269: int sta; ! 11270: int n_q_required; ! 11271: int disable_syn_offset_one_fix; ! 11272: int i; ! 11273: ulong addr; ! 11274: ASC_EXE_CALLBACK asc_exe_callback; ! 11275: ushort sg_entry_cnt = 0; ! 11276: ushort sg_entry_cnt_minus_one = 0; ! 11277: uchar target_ix; ! 11278: uchar tid_no; ! 11279: uchar sdtr_data; ! 11280: uchar extra_bytes; ! 11281: uchar scsi_cmd; ! 11282: uchar disable_cmd; ! 11283: ASC_SG_HEAD *sg_head; ! 11284: ulong data_cnt; ! 11285: ! 11286: iop_base = asc_dvc->iop_base; ! 11287: sg_head = scsiq->sg_head; ! 11288: asc_exe_callback = (ASC_EXE_CALLBACK) asc_dvc->exe_callback; ! 11289: if (asc_dvc->err_code != 0) ! 11290: return (ERR); ! 11291: if (scsiq == (ASC_SCSI_Q *) 0L) { ! 11292: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR); ! 11293: return (ERR); ! 11294: } ! 11295: scsiq->q1.q_no = 0; ! 11296: if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) { ! 11297: scsiq->q1.extra_bytes = 0; ! 11298: } ! 11299: sta = 0; ! 11300: target_ix = scsiq->q2.target_ix; ! 11301: tid_no = ASC_TIX_TO_TID(target_ix); ! 11302: n_q_required = 1; ! 11303: if (scsiq->cdbptr[0] == SCSICMD_RequestSense) { ! 11304: if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) { ! 11305: asc_dvc->sdtr_done &= ~scsiq->q1.target_id ; ! 11306: sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); ! 11307: AscMsgOutSDTR(asc_dvc, ! 11308: asc_dvc->sdtr_period_tbl[(sdtr_data >> 4) & ! 11309: (uchar) (asc_dvc->max_sdtr_index - 1)], ! 11310: (uchar) (sdtr_data & (uchar) ASC_SYN_MAX_OFFSET)); ! 11311: scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT); ! 11312: } ! 11313: } ! 11314: last_int_level = DvcEnterCritical(); ! 11315: if (asc_dvc->in_critical_cnt != 0) { ! 11316: DvcLeaveCritical(last_int_level); ! 11317: AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY); ! 11318: return (ERR); ! 11319: } ! 11320: asc_dvc->in_critical_cnt++; ! 11321: if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { ! 11322: if ((sg_entry_cnt = sg_head->entry_cnt) == 0) { ! 11323: asc_dvc->in_critical_cnt--; ! 11324: DvcLeaveCritical(last_int_level); ! 11325: return (ERR); ! 11326: } ! 11327: if (sg_entry_cnt > ASC_MAX_SG_LIST) { ! 11328: return (ERR); ! 11329: } ! 11330: if (sg_entry_cnt == 1) { ! 11331: scsiq->q1.data_addr = sg_head->sg_list[0].addr; ! 11332: scsiq->q1.data_cnt = sg_head->sg_list[0].bytes; ! 11333: scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE); ! 11334: } ! 11335: sg_entry_cnt_minus_one = sg_entry_cnt - 1; ! 11336: } ! 11337: scsi_cmd = scsiq->cdbptr[0]; ! 11338: disable_syn_offset_one_fix = FALSE; ! 11339: if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) && ! 11340: !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) { ! 11341: if (scsiq->q1.cntl & QC_SG_HEAD) { ! 11342: data_cnt = 0; ! 11343: for (i = 0; i < sg_entry_cnt; i++) { ! 11344: data_cnt += sg_head->sg_list[i].bytes; ! 11345: } ! 11346: } else { ! 11347: data_cnt = scsiq->q1.data_cnt; ! 11348: } ! 11349: if (data_cnt != 0UL) { ! 11350: if (data_cnt < 512UL) { ! 11351: disable_syn_offset_one_fix = TRUE; ! 11352: } else { ! 11353: for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; i++) { ! 11354: disable_cmd = _syn_offset_one_disable_cmd[i]; ! 11355: if (disable_cmd == 0xFF) { ! 11356: break; ! 11357: } ! 11358: if (scsi_cmd == disable_cmd) { ! 11359: disable_syn_offset_one_fix = TRUE; ! 11360: break; ! 11361: } ! 11362: } ! 11363: } ! 11364: } ! 11365: } ! 11366: if (disable_syn_offset_one_fix) { ! 11367: scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE; ! 11368: scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX | ! 11369: ASC_TAG_FLAG_DISABLE_DISCONNECT); ! 11370: } else { ! 11371: scsiq->q2.tag_code &= 0x23; ! 11372: } ! 11373: if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { ! 11374: if (asc_dvc->bug_fix_cntl) { ! 11375: if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { ! 11376: if ((scsi_cmd == SCSICMD_Read6) || ! 11377: (scsi_cmd == SCSICMD_Read10)) { ! 11378: addr = sg_head->sg_list[sg_entry_cnt_minus_one].addr + ! 11379: sg_head->sg_list[sg_entry_cnt_minus_one].bytes; ! 11380: extra_bytes = (uchar) ((ushort) addr & 0x0003); ! 11381: if ((extra_bytes != 0) && ! 11382: ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) ! 11383: == 0)) { ! 11384: scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES; ! 11385: scsiq->q1.extra_bytes = extra_bytes; ! 11386: sg_head->sg_list[sg_entry_cnt_minus_one].bytes -= ! 11387: (ulong) extra_bytes; ! 11388: } ! 11389: } ! 11390: } ! 11391: } ! 11392: sg_head->entry_to_copy = sg_head->entry_cnt; ! 11393: n_q_required = AscSgListToQueue(sg_entry_cnt); ! 11394: if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >= ! 11395: (uint) n_q_required) || ((scsiq->q1.cntl & QC_URGENT) != 0)) { ! 11396: if ((sta = AscSendScsiQueue(asc_dvc, scsiq, ! 11397: n_q_required)) == 1) { ! 11398: asc_dvc->in_critical_cnt--; ! 11399: if (asc_exe_callback != 0) { ! 11400: (*asc_exe_callback) (asc_dvc, scsiq); ! 11401: } ! 11402: DvcLeaveCritical(last_int_level); ! 11403: return (sta); ! 11404: } ! 11405: } ! 11406: } else { ! 11407: if (asc_dvc->bug_fix_cntl) { ! 11408: if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { ! 11409: if ((scsi_cmd == SCSICMD_Read6) || ! 11410: (scsi_cmd == SCSICMD_Read10)) { ! 11411: addr = scsiq->q1.data_addr + scsiq->q1.data_cnt; ! 11412: extra_bytes = (uchar) ((ushort) addr & 0x0003); ! 11413: if ((extra_bytes != 0) && ! 11414: ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) ! 11415: == 0)) { ! 11416: if (((ushort) scsiq->q1.data_cnt & 0x01FF) == 0) { ! 11417: scsiq->q2.tag_code |= ASC_TAG_FLAG_EXTRA_BYTES; ! 11418: scsiq->q1.data_cnt -= (ulong) extra_bytes; ! 11419: scsiq->q1.extra_bytes = extra_bytes; ! 11420: } ! 11421: } ! 11422: } ! 11423: } ! 11424: } ! 11425: n_q_required = 1; ! 11426: if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) || ! 11427: ((scsiq->q1.cntl & QC_URGENT) != 0)) { ! 11428: if ((sta = AscSendScsiQueue(asc_dvc, scsiq, ! 11429: n_q_required)) == 1) { ! 11430: asc_dvc->in_critical_cnt--; ! 11431: if (asc_exe_callback != 0) { ! 11432: (*asc_exe_callback) (asc_dvc, scsiq); ! 11433: } ! 11434: DvcLeaveCritical(last_int_level); ! 11435: return (sta); ! 11436: } ! 11437: } ! 11438: } ! 11439: asc_dvc->in_critical_cnt--; ! 11440: DvcLeaveCritical(last_int_level); ! 11441: return (sta); ! 11442: } ! 11443: ! 11444: STATIC int ! 11445: AscSendScsiQueue( ! 11446: REG ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 11447: REG ASC_SCSI_Q * scsiq, ! 11448: uchar n_q_required ! 11449: ) ! 11450: { ! 11451: PortAddr iop_base; ! 11452: uchar free_q_head; ! 11453: uchar next_qp; ! 11454: uchar tid_no; ! 11455: uchar target_ix; ! 11456: int sta; ! 11457: ! 11458: iop_base = asc_dvc->iop_base; ! 11459: target_ix = scsiq->q2.target_ix; ! 11460: tid_no = ASC_TIX_TO_TID(target_ix); ! 11461: sta = 0; ! 11462: free_q_head = (uchar) AscGetVarFreeQHead(iop_base); ! 11463: if (n_q_required > 1) { ! 11464: if ((next_qp = AscAllocMultipleFreeQueue(iop_base, ! 11465: free_q_head, (uchar) (n_q_required))) ! 11466: != (uchar) ASC_QLINK_END) { ! 11467: asc_dvc->last_q_shortage = 0; ! 11468: scsiq->sg_head->queue_cnt = n_q_required - 1; ! 11469: scsiq->q1.q_no = free_q_head; ! 11470: if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq, ! 11471: free_q_head)) == 1) { ! 11472: AscPutVarFreeQHead(iop_base, next_qp); ! 11473: asc_dvc->cur_total_qng += (uchar) (n_q_required); ! 11474: asc_dvc->cur_dvc_qng[tid_no]++; ! 11475: } ! 11476: return (sta); ! 11477: } ! 11478: } else if (n_q_required == 1) { ! 11479: if ((next_qp = AscAllocFreeQueue(iop_base, ! 11480: free_q_head)) != ASC_QLINK_END) { ! 11481: scsiq->q1.q_no = free_q_head; ! 11482: if ((sta = AscPutReadyQueue(asc_dvc, scsiq, ! 11483: free_q_head)) == 1) { ! 11484: AscPutVarFreeQHead(iop_base, next_qp); ! 11485: asc_dvc->cur_total_qng++; ! 11486: asc_dvc->cur_dvc_qng[tid_no]++; ! 11487: } ! 11488: return (sta); ! 11489: } ! 11490: } ! 11491: return (sta); ! 11492: } ! 11493: ! 11494: STATIC int ! 11495: AscSgListToQueue( ! 11496: int sg_list ! 11497: ) ! 11498: { ! 11499: int n_sg_list_qs; ! 11500: ! 11501: n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q); ! 11502: if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0) ! 11503: n_sg_list_qs++; ! 11504: return (n_sg_list_qs + 1); ! 11505: } ! 11506: ! 11507: ! 11508: STATIC uint ! 11509: AscGetNumOfFreeQueue( ! 11510: REG ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 11511: uchar target_ix, ! 11512: uchar n_qs ! 11513: ) ! 11514: { ! 11515: uint cur_used_qs; ! 11516: uint cur_free_qs; ! 11517: ASC_SCSI_BIT_ID_TYPE target_id; ! 11518: uchar tid_no; ! 11519: ! 11520: target_id = ASC_TIX_TO_TARGET_ID(target_ix); ! 11521: tid_no = ASC_TIX_TO_TID(target_ix); ! 11522: if ((asc_dvc->unit_not_ready & target_id) || ! 11523: (asc_dvc->queue_full_or_busy & target_id)) { ! 11524: return (0); ! 11525: } ! 11526: if (n_qs == 1) { ! 11527: cur_used_qs = (uint) asc_dvc->cur_total_qng + ! 11528: (uint) asc_dvc->last_q_shortage + ! 11529: (uint) ASC_MIN_FREE_Q; ! 11530: } else { ! 11531: cur_used_qs = (uint) asc_dvc->cur_total_qng + ! 11532: (uint) ASC_MIN_FREE_Q; ! 11533: } ! 11534: if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) { ! 11535: cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs; ! 11536: if (asc_dvc->cur_dvc_qng[tid_no] >= ! 11537: asc_dvc->max_dvc_qng[tid_no]) { ! 11538: return (0); ! 11539: } ! 11540: return (cur_free_qs); ! 11541: } ! 11542: if (n_qs > 1) { ! 11543: if ((n_qs > asc_dvc->last_q_shortage) && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) { ! 11544: asc_dvc->last_q_shortage = n_qs; ! 11545: } ! 11546: } ! 11547: return (0); ! 11548: } ! 11549: ! 11550: STATIC int ! 11551: AscPutReadyQueue( ! 11552: REG ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 11553: REG ASC_SCSI_Q * scsiq, ! 11554: uchar q_no ! 11555: ) ! 11556: { ! 11557: ushort q_addr; ! 11558: uchar tid_no; ! 11559: uchar sdtr_data; ! 11560: uchar syn_period_ix; ! 11561: uchar syn_offset; ! 11562: PortAddr iop_base; ! 11563: ! 11564: iop_base = asc_dvc->iop_base; ! 11565: if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) && ! 11566: ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) { ! 11567: tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix); ! 11568: sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); ! 11569: syn_period_ix = (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1); ! 11570: syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET; ! 11571: AscMsgOutSDTR(asc_dvc, ! 11572: asc_dvc->sdtr_period_tbl[syn_period_ix], ! 11573: syn_offset); ! 11574: scsiq->q1.cntl |= QC_MSG_OUT; ! 11575: } ! 11576: q_addr = ASC_QNO_TO_QADDR(q_no); ! 11577: if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) { ! 11578: scsiq->q2.tag_code &= ~M2_QTAG_MSG_SIMPLE; ! 11579: } ! 11580: scsiq->q1.status = QS_FREE; ! 11581: AscMemWordCopyToLram(iop_base, ! 11582: (ushort) (q_addr + (ushort) ASC_SCSIQ_CDB_BEG), ! 11583: (ushort *) scsiq->cdbptr, ! 11584: (ushort) ((ushort) scsiq->q2.cdb_len >> 1)); ! 11585: DvcPutScsiQ(iop_base, ! 11586: (ushort) (q_addr + (ushort) ASC_SCSIQ_CPY_BEG), ! 11587: (ushort *) & scsiq->q1.cntl, ! 11588: (ushort) ((((sizeof (ASC_SCSIQ_1) + sizeof (ASC_SCSIQ_2)) / 2) - 1))); ! 11589: AscWriteLramWord(iop_base, ! 11590: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), ! 11591: (ushort) (((ushort) scsiq->q1.q_no << 8) | (ushort) QS_READY)); ! 11592: return (1); ! 11593: } ! 11594: ! 11595: STATIC int ! 11596: AscPutReadySgListQueue( ! 11597: REG ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 11598: REG ASC_SCSI_Q * scsiq, ! 11599: uchar q_no ! 11600: ) ! 11601: { ! 11602: int sta; ! 11603: int i; ! 11604: ASC_SG_HEAD *sg_head; ! 11605: ASC_SG_LIST_Q scsi_sg_q; ! 11606: ulong saved_data_addr; ! 11607: ulong saved_data_cnt; ! 11608: PortAddr iop_base; ! 11609: ushort sg_list_dwords; ! 11610: ushort sg_index; ! 11611: ushort sg_entry_cnt; ! 11612: ushort q_addr; ! 11613: uchar next_qp; ! 11614: ! 11615: iop_base = asc_dvc->iop_base; ! 11616: sg_head = scsiq->sg_head; ! 11617: saved_data_addr = scsiq->q1.data_addr; ! 11618: saved_data_cnt = scsiq->q1.data_cnt; ! 11619: scsiq->q1.data_addr = sg_head->sg_list[0].addr; ! 11620: scsiq->q1.data_cnt = sg_head->sg_list[0].bytes; ! 11621: sg_entry_cnt = sg_head->entry_cnt - 1; ! 11622: if (sg_entry_cnt != 0) { ! 11623: scsiq->q1.cntl |= QC_SG_HEAD; ! 11624: q_addr = ASC_QNO_TO_QADDR(q_no); ! 11625: sg_index = 1; ! 11626: scsiq->q1.sg_queue_cnt = sg_head->queue_cnt; ! 11627: scsi_sg_q.sg_head_qp = q_no; ! 11628: scsi_sg_q.cntl = QCSG_SG_XFER_LIST; ! 11629: for (i = 0; i < sg_head->queue_cnt; i++) { ! 11630: scsi_sg_q.seq_no = i + 1; ! 11631: if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { ! 11632: sg_list_dwords = (uchar) (ASC_SG_LIST_PER_Q * 2); ! 11633: sg_entry_cnt -= ASC_SG_LIST_PER_Q; ! 11634: if (i == 0) { ! 11635: scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q; ! 11636: scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q; ! 11637: } else { ! 11638: scsi_sg_q.sg_list_cnt = ASC_SG_LIST_PER_Q - 1; ! 11639: scsi_sg_q.sg_cur_list_cnt = ASC_SG_LIST_PER_Q - 1; ! 11640: } ! 11641: } else { ! 11642: scsi_sg_q.cntl |= QCSG_SG_XFER_END; ! 11643: sg_list_dwords = sg_entry_cnt << 1; ! 11644: if (i == 0) { ! 11645: scsi_sg_q.sg_list_cnt = sg_entry_cnt; ! 11646: scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt; ! 11647: } else { ! 11648: scsi_sg_q.sg_list_cnt = sg_entry_cnt - 1; ! 11649: scsi_sg_q.sg_cur_list_cnt = sg_entry_cnt - 1; ! 11650: } ! 11651: sg_entry_cnt = 0; ! 11652: } ! 11653: next_qp = AscReadLramByte(iop_base, ! 11654: (ushort) (q_addr + ASC_SCSIQ_B_FWD)); ! 11655: scsi_sg_q.q_no = next_qp; ! 11656: q_addr = ASC_QNO_TO_QADDR(next_qp); ! 11657: AscMemWordCopyToLram(iop_base, ! 11658: (ushort) (q_addr + ASC_SCSIQ_SGHD_CPY_BEG), ! 11659: (ushort *) & scsi_sg_q, ! 11660: (ushort) (sizeof (ASC_SG_LIST_Q) >> 1)); ! 11661: AscMemDWordCopyToLram(iop_base, ! 11662: (ushort) (q_addr + ASC_SGQ_LIST_BEG), ! 11663: (ulong *) & sg_head->sg_list[sg_index], ! 11664: (ushort) sg_list_dwords); ! 11665: sg_index += ASC_SG_LIST_PER_Q; ! 11666: } ! 11667: } else { ! 11668: scsiq->q1.cntl &= ~QC_SG_HEAD; ! 11669: } ! 11670: sta = AscPutReadyQueue(asc_dvc, scsiq, q_no); ! 11671: scsiq->q1.data_addr = saved_data_addr; ! 11672: scsiq->q1.data_cnt = saved_data_cnt; ! 11673: return (sta); ! 11674: } ! 11675: ! 11676: STATIC int ! 11677: AscAbortSRB( ! 11678: REG ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 11679: ulong srb_ptr ! 11680: ) ! 11681: { ! 11682: int sta; ! 11683: ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready; ! 11684: PortAddr iop_base; ! 11685: ! 11686: iop_base = asc_dvc->iop_base; ! 11687: sta = ERR; ! 11688: saved_unit_not_ready = asc_dvc->unit_not_ready; ! 11689: asc_dvc->unit_not_ready = 0xFF; ! 11690: AscWaitISRDone(asc_dvc); ! 11691: if (AscStopQueueExe(iop_base) == 1) { ! 11692: if (AscRiscHaltedAbortSRB(asc_dvc, srb_ptr) == 1) { ! 11693: sta = 1; ! 11694: AscCleanUpBusyQueue(iop_base); ! 11695: AscStartQueueExe(iop_base); ! 11696: } else { ! 11697: sta = 0; ! 11698: AscStartQueueExe(iop_base); ! 11699: } ! 11700: } ! 11701: asc_dvc->unit_not_ready = saved_unit_not_ready; ! 11702: return (sta); ! 11703: } ! 11704: ! 11705: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 11706: STATIC int ! 11707: AscResetDevice( ! 11708: REG ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 11709: uchar target_ix ! 11710: ) ! 11711: { ! 11712: PortAddr iop_base; ! 11713: int sta; ! 11714: uchar tid_no; ! 11715: ! 11716: ASC_SCSI_BIT_ID_TYPE target_id; ! 11717: int i; ! 11718: ASC_SCSI_REQ_Q scsiq_buf; ! 11719: ASC_SCSI_REQ_Q *scsiq; ! 11720: uchar *buf; ! 11721: ASC_SCSI_BIT_ID_TYPE saved_unit_not_ready; ! 11722: iop_base = asc_dvc->iop_base; ! 11723: tid_no = ASC_TIX_TO_TID(target_ix); ! 11724: target_id = ASC_TID_TO_TARGET_ID(tid_no); ! 11725: saved_unit_not_ready = asc_dvc->unit_not_ready; ! 11726: asc_dvc->unit_not_ready = target_id; ! 11727: sta = ERR; ! 11728: AscWaitTixISRDone(asc_dvc, target_ix); ! 11729: if (AscStopQueueExe(iop_base) == 1) { ! 11730: if (AscRiscHaltedAbortTIX(asc_dvc, target_ix) == 1) { ! 11731: AscCleanUpBusyQueue(iop_base); ! 11732: AscStartQueueExe(iop_base); ! 11733: AscWaitTixISRDone(asc_dvc, target_ix); ! 11734: sta = TRUE; ! 11735: scsiq = (ASC_SCSI_REQ_Q *) & scsiq_buf; ! 11736: buf = (uchar *) & scsiq_buf; ! 11737: for (i = 0; i < sizeof (ASC_SCSI_REQ_Q); i++) { ! 11738: *buf++ = 0x00; ! 11739: } ! 11740: scsiq->r1.status = (uchar) QS_READY; ! 11741: scsiq->r2.cdb_len = 6; ! 11742: scsiq->r2.tag_code = M2_QTAG_MSG_SIMPLE; ! 11743: scsiq->r1.target_id = target_id; ! 11744: scsiq->r2.target_ix = ASC_TIDLUN_TO_IX(tid_no, 0); ! 11745: scsiq->cdbptr = (uchar *) scsiq->cdb; ! 11746: scsiq->r1.cntl = QC_NO_CALLBACK | QC_MSG_OUT | QC_URGENT; ! 11747: AscWriteLramByte(asc_dvc->iop_base, ASCV_MSGOUT_BEG, ! 11748: M1_BUS_DVC_RESET); ! 11749: asc_dvc->unit_not_ready &= ~target_id; ! 11750: asc_dvc->sdtr_done |= target_id; ! 11751: if (AscExeScsiQueue(asc_dvc, (ASC_SCSI_Q *) scsiq) ! 11752: == 1) { ! 11753: asc_dvc->unit_not_ready = target_id; ! 11754: DvcSleepMilliSecond(1000); ! 11755: _AscWaitQDone(iop_base, (ASC_SCSI_Q *) scsiq); ! 11756: if (AscStopQueueExe(iop_base) == 1) { ! 11757: AscCleanUpDiscQueue(iop_base); ! 11758: AscStartQueueExe(iop_base); ! 11759: if (asc_dvc->pci_fix_asyn_xfer & target_id) { ! 11760: AscSetRunChipSynRegAtID(iop_base, tid_no, ! 11761: ASYN_SDTR_DATA_FIX_PCI_REV_AB); ! 11762: } ! 11763: AscWaitTixISRDone(asc_dvc, target_ix); ! 11764: } ! 11765: } else { ! 11766: sta = 0; ! 11767: } ! 11768: asc_dvc->sdtr_done &= ~target_id; ! 11769: } else { ! 11770: sta = ERR; ! 11771: AscStartQueueExe(iop_base); ! 11772: } ! 11773: } ! 11774: asc_dvc->unit_not_ready = saved_unit_not_ready; ! 11775: return (sta); ! 11776: } ! 11777: #endif /* version >= v1.3.89 */ ! 11778: ! 11779: STATIC int ! 11780: AscResetSB( ! 11781: REG ASC_DVC_VAR asc_ptr_type * asc_dvc ! 11782: ) ! 11783: { ! 11784: int sta; ! 11785: int i; ! 11786: PortAddr iop_base; ! 11787: ! 11788: iop_base = asc_dvc->iop_base; ! 11789: asc_dvc->unit_not_ready = 0xFF; ! 11790: sta = TRUE; ! 11791: AscWaitISRDone(asc_dvc); ! 11792: AscStopQueueExe(iop_base); ! 11793: asc_dvc->sdtr_done = 0; ! 11794: AscResetChipAndScsiBus(asc_dvc); ! 11795: DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000)); ! 11796: AscReInitLram(asc_dvc); ! 11797: for (i = 0; i <= ASC_MAX_TID; i++) { ! 11798: asc_dvc->cur_dvc_qng[i] = 0; ! 11799: if (asc_dvc->pci_fix_asyn_xfer & (ASC_SCSI_BIT_ID_TYPE) (0x01 << i)) { ! 11800: AscSetChipSynRegAtID(iop_base, i, ASYN_SDTR_DATA_FIX_PCI_REV_AB); ! 11801: } ! 11802: } ! 11803: asc_dvc->err_code = 0; ! 11804: AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); ! 11805: if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { ! 11806: sta = ERR; ! 11807: } ! 11808: if (AscStartChip(iop_base) == 0) { ! 11809: sta = ERR; ! 11810: } ! 11811: AscStartQueueExe(iop_base); ! 11812: asc_dvc->unit_not_ready = 0; ! 11813: asc_dvc->queue_full_or_busy = 0; ! 11814: return (sta); ! 11815: } ! 11816: ! 11817: STATIC int ! 11818: AscSetRunChipSynRegAtID( ! 11819: PortAddr iop_base, ! 11820: uchar tid_no, ! 11821: uchar sdtr_data ! 11822: ) ! 11823: { ! 11824: int sta = FALSE; ! 11825: ! 11826: if (AscHostReqRiscHalt(iop_base)) { ! 11827: sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); ! 11828: AscStartChip(iop_base); ! 11829: return (sta); ! 11830: } ! 11831: return (sta); ! 11832: } ! 11833: ! 11834: STATIC int ! 11835: AscSetChipSynRegAtID( ! 11836: PortAddr iop_base, ! 11837: uchar id, ! 11838: uchar sdtr_data ! 11839: ) ! 11840: { ! 11841: ASC_SCSI_BIT_ID_TYPE org_id; ! 11842: int i; ! 11843: int sta = TRUE; ! 11844: ! 11845: AscSetBank(iop_base, 1); ! 11846: org_id = AscReadChipDvcID(iop_base); ! 11847: for (i = 0; i <= ASC_MAX_TID; i++) { ! 11848: if (org_id == (0x01 << i)) ! 11849: break; ! 11850: } ! 11851: org_id = i; ! 11852: AscWriteChipDvcID(iop_base, id); ! 11853: if (AscReadChipDvcID(iop_base) == (0x01 << id)) { ! 11854: AscSetBank(iop_base, 0); ! 11855: AscSetChipSyn(iop_base, sdtr_data); ! 11856: if (AscGetChipSyn(iop_base) != sdtr_data) { ! 11857: sta = FALSE; ! 11858: } ! 11859: } else { ! 11860: sta = FALSE; ! 11861: } ! 11862: AscSetBank(iop_base, 1); ! 11863: AscWriteChipDvcID(iop_base, org_id); ! 11864: AscSetBank(iop_base, 0); ! 11865: return (sta); ! 11866: } ! 11867: ! 11868: STATIC int ! 11869: AscReInitLram( ! 11870: REG ASC_DVC_VAR asc_ptr_type * asc_dvc ! 11871: ) ! 11872: { ! 11873: AscInitLram(asc_dvc); ! 11874: AscInitQLinkVar(asc_dvc); ! 11875: return (0); ! 11876: } ! 11877: ! 11878: STATIC ushort ! 11879: AscInitLram( ! 11880: REG ASC_DVC_VAR asc_ptr_type * asc_dvc ! 11881: ) ! 11882: { ! 11883: uchar i; ! 11884: ushort s_addr; ! 11885: PortAddr iop_base; ! 11886: ushort warn_code; ! 11887: ! 11888: iop_base = asc_dvc->iop_base; ! 11889: warn_code = 0; ! 11890: AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0, ! 11891: (ushort) (((int) (asc_dvc->max_total_qng + 2 + 1) * 64) >> 1) ! 11892: ); ! 11893: i = ASC_MIN_ACTIVE_QNO; ! 11894: s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE; ! 11895: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), ! 11896: (uchar) (i + 1)); ! 11897: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), ! 11898: (uchar) (asc_dvc->max_total_qng)); ! 11899: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), ! 11900: (uchar) i); ! 11901: i++; ! 11902: s_addr += ASC_QBLK_SIZE; ! 11903: for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) { ! 11904: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), ! 11905: (uchar) (i + 1)); ! 11906: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), ! 11907: (uchar) (i - 1)); ! 11908: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), ! 11909: (uchar) i); ! 11910: } ! 11911: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_FWD), ! 11912: (uchar) ASC_QLINK_END); ! 11913: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_BWD), ! 11914: (uchar) (asc_dvc->max_total_qng - 1)); ! 11915: AscWriteLramByte(iop_base, (ushort) (s_addr + ASC_SCSIQ_B_QNO), ! 11916: (uchar) asc_dvc->max_total_qng); ! 11917: i++; ! 11918: s_addr += ASC_QBLK_SIZE; ! 11919: for (; i <= (uchar) (asc_dvc->max_total_qng + 3); ! 11920: i++, s_addr += ASC_QBLK_SIZE) { ! 11921: AscWriteLramByte(iop_base, ! 11922: (ushort) (s_addr + (ushort) ASC_SCSIQ_B_FWD), i); ! 11923: AscWriteLramByte(iop_base, ! 11924: (ushort) (s_addr + (ushort) ASC_SCSIQ_B_BWD), i); ! 11925: AscWriteLramByte(iop_base, ! 11926: (ushort) (s_addr + (ushort) ASC_SCSIQ_B_QNO), i); ! 11927: } ! 11928: return (warn_code); ! 11929: } ! 11930: ! 11931: STATIC ushort ! 11932: AscInitQLinkVar( ! 11933: REG ASC_DVC_VAR asc_ptr_type * asc_dvc ! 11934: ) ! 11935: { ! 11936: PortAddr iop_base; ! 11937: int i; ! 11938: ushort lram_addr; ! 11939: ! 11940: iop_base = asc_dvc->iop_base; ! 11941: AscPutRiscVarFreeQHead(iop_base, 1); ! 11942: AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng); ! 11943: AscPutVarFreeQHead(iop_base, 1); ! 11944: AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng); ! 11945: AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B, ! 11946: (uchar) ((int) asc_dvc->max_total_qng + 1)); ! 11947: AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B, ! 11948: (uchar) ((int) asc_dvc->max_total_qng + 2)); ! 11949: AscWriteLramByte(iop_base, (ushort) ASCV_TOTAL_READY_Q_B, ! 11950: asc_dvc->max_total_qng); ! 11951: AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0); ! 11952: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); ! 11953: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0); ! 11954: AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0); ! 11955: AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0); ! 11956: AscPutQDoneInProgress(iop_base, 0); ! 11957: lram_addr = ASC_QADR_BEG; ! 11958: for (i = 0; i < 32; i++, lram_addr += 2) { ! 11959: AscWriteLramWord(iop_base, lram_addr, 0); ! 11960: } ! 11961: return (0); ! 11962: } ! 11963: ! 11964: STATIC int ! 11965: AscSetLibErrorCode( ! 11966: REG ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 11967: ushort err_code ! 11968: ) ! 11969: { ! 11970: if (asc_dvc->err_code == 0) { ! 11971: asc_dvc->err_code = err_code; ! 11972: AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W, ! 11973: err_code); ! 11974: } ! 11975: return (err_code); ! 11976: } ! 11977: ! 11978: ! 11979: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 11980: STATIC int ! 11981: _AscWaitQDone( ! 11982: PortAddr iop_base, ! 11983: REG ASC_SCSI_Q * scsiq ! 11984: ) ! 11985: { ! 11986: ushort q_addr; ! 11987: uchar q_status; ! 11988: int count = 0; ! 11989: ! 11990: while (scsiq->q1.q_no == 0) ; ! 11991: q_addr = ASC_QNO_TO_QADDR(scsiq->q1.q_no); ! 11992: do { ! 11993: q_status = AscReadLramByte(iop_base, q_addr + ASC_SCSIQ_B_STATUS); ! 11994: DvcSleepMilliSecond(100L); ! 11995: if (count++ > 30) { ! 11996: return (0); ! 11997: } ! 11998: } while ((q_status & QS_READY) != 0); ! 11999: return (1); ! 12000: } ! 12001: #endif /* version >= v1.3.89 */ ! 12002: ! 12003: STATIC uchar ! 12004: AscMsgOutSDTR( ! 12005: REG ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 12006: uchar sdtr_period, ! 12007: uchar sdtr_offset ! 12008: ) ! 12009: { ! 12010: EXT_MSG sdtr_buf; ! 12011: uchar sdtr_period_index; ! 12012: PortAddr iop_base; ! 12013: ! 12014: iop_base = asc_dvc->iop_base; ! 12015: sdtr_buf.msg_type = MS_EXTEND; ! 12016: sdtr_buf.msg_len = MS_SDTR_LEN; ! 12017: sdtr_buf.msg_req = MS_SDTR_CODE; ! 12018: sdtr_buf.xfer_period = sdtr_period; ! 12019: sdtr_offset &= ASC_SYN_MAX_OFFSET; ! 12020: sdtr_buf.req_ack_offset = sdtr_offset; ! 12021: if ((sdtr_period_index = ! 12022: AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <= ! 12023: asc_dvc->max_sdtr_index) { ! 12024: AscMemWordCopyToLram(iop_base, ! 12025: ASCV_MSGOUT_BEG, ! 12026: (ushort *) & sdtr_buf, ! 12027: (ushort) (sizeof (EXT_MSG) >> 1)); ! 12028: return ((sdtr_period_index << 4) | sdtr_offset); ! 12029: } else { ! 12030: ! 12031: sdtr_buf.req_ack_offset = 0; ! 12032: AscMemWordCopyToLram(iop_base, ! 12033: ASCV_MSGOUT_BEG, ! 12034: (ushort *) & sdtr_buf, ! 12035: (ushort) (sizeof (EXT_MSG) >> 1)); ! 12036: return (0); ! 12037: } ! 12038: } ! 12039: ! 12040: STATIC uchar ! 12041: AscCalSDTRData( ! 12042: REG ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 12043: uchar sdtr_period, ! 12044: uchar syn_offset ! 12045: ) ! 12046: { ! 12047: uchar byte; ! 12048: uchar sdtr_period_ix; ! 12049: ! 12050: sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period); ! 12051: if ( ! 12052: (sdtr_period_ix > asc_dvc->max_sdtr_index) ! 12053: ) { ! 12054: return (0xFF); ! 12055: } ! 12056: byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET); ! 12057: return (byte); ! 12058: } ! 12059: ! 12060: STATIC void ! 12061: AscSetChipSDTR( ! 12062: PortAddr iop_base, ! 12063: uchar sdtr_data, ! 12064: uchar tid_no ! 12065: ) ! 12066: { ! 12067: AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); ! 12068: AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data); ! 12069: return; ! 12070: } ! 12071: ! 12072: STATIC uchar ! 12073: AscGetSynPeriodIndex( ! 12074: ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 12075: ruchar syn_time ! 12076: ) ! 12077: { ! 12078: ruchar *period_table; ! 12079: int max_index; ! 12080: int min_index; ! 12081: int i; ! 12082: ! 12083: period_table = asc_dvc->sdtr_period_tbl; ! 12084: max_index = (int) asc_dvc->max_sdtr_index; ! 12085: min_index = (int)asc_dvc->host_init_sdtr_index ; ! 12086: if ((syn_time <= period_table[max_index])) { ! 12087: for (i = min_index; i < (max_index - 1); i++) { ! 12088: if (syn_time <= period_table[i]) { ! 12089: return ((uchar) i); ! 12090: } ! 12091: } ! 12092: return ((uchar) max_index); ! 12093: } else { ! 12094: return ((uchar) (max_index + 1)); ! 12095: } ! 12096: } ! 12097: ! 12098: STATIC uchar ! 12099: AscAllocFreeQueue( ! 12100: PortAddr iop_base, ! 12101: uchar free_q_head ! 12102: ) ! 12103: { ! 12104: ushort q_addr; ! 12105: uchar next_qp; ! 12106: uchar q_status; ! 12107: ! 12108: q_addr = ASC_QNO_TO_QADDR(free_q_head); ! 12109: q_status = (uchar) AscReadLramByte(iop_base, ! 12110: (ushort) (q_addr + ASC_SCSIQ_B_STATUS)); ! 12111: next_qp = AscReadLramByte(iop_base, ! 12112: (ushort) (q_addr + ASC_SCSIQ_B_FWD)); ! 12113: if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) { ! 12114: return (next_qp); ! 12115: } ! 12116: return (ASC_QLINK_END); ! 12117: } ! 12118: ! 12119: STATIC uchar ! 12120: AscAllocMultipleFreeQueue( ! 12121: PortAddr iop_base, ! 12122: uchar free_q_head, ! 12123: uchar n_free_q ! 12124: ) ! 12125: { ! 12126: uchar i; ! 12127: ! 12128: for (i = 0; i < n_free_q; i++) { ! 12129: if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head)) ! 12130: == ASC_QLINK_END) { ! 12131: return (ASC_QLINK_END); ! 12132: } ! 12133: } ! 12134: return (free_q_head); ! 12135: } ! 12136: ! 12137: STATIC int ! 12138: AscRiscHaltedAbortSRB( ! 12139: REG ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 12140: ulong srb_ptr ! 12141: ) ! 12142: { ! 12143: PortAddr iop_base; ! 12144: ushort q_addr; ! 12145: uchar q_no; ! 12146: ASC_QDONE_INFO scsiq_buf; ! 12147: ASC_QDONE_INFO *scsiq; ! 12148: ASC_ISR_CALLBACK asc_isr_callback; ! 12149: int last_int_level; ! 12150: ! 12151: iop_base = asc_dvc->iop_base; ! 12152: asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback; ! 12153: last_int_level = DvcEnterCritical(); ! 12154: scsiq = (ASC_QDONE_INFO *) & scsiq_buf; ! 12155: for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng; ! 12156: q_no++) { ! 12157: q_addr = ASC_QNO_TO_QADDR(q_no); ! 12158: scsiq->d2.srb_ptr = AscReadLramDWord(iop_base, ! 12159: (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR)); ! 12160: if (scsiq->d2.srb_ptr == srb_ptr) { ! 12161: _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count); ! 12162: if (((scsiq->q_status & QS_READY) != 0) ! 12163: && ((scsiq->q_status & QS_ABORTED) == 0) ! 12164: && ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) { ! 12165: scsiq->q_status |= QS_ABORTED; ! 12166: scsiq->d3.done_stat = QD_ABORTED_BY_HOST; ! 12167: AscWriteLramDWord(iop_base, ! 12168: (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR), ! 12169: 0L); ! 12170: AscWriteLramByte(iop_base, ! 12171: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), ! 12172: scsiq->q_status); ! 12173: (*asc_isr_callback) (asc_dvc, scsiq); ! 12174: return (1); ! 12175: } ! 12176: } ! 12177: } ! 12178: DvcLeaveCritical(last_int_level); ! 12179: return (0); ! 12180: } ! 12181: ! 12182: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 12183: STATIC int ! 12184: AscRiscHaltedAbortTIX( ! 12185: REG ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 12186: uchar target_ix ! 12187: ) ! 12188: { ! 12189: PortAddr iop_base; ! 12190: ushort q_addr; ! 12191: uchar q_no; ! 12192: ASC_QDONE_INFO scsiq_buf; ! 12193: ASC_QDONE_INFO *scsiq; ! 12194: ASC_ISR_CALLBACK asc_isr_callback; ! 12195: int last_int_level; ! 12196: ! 12197: iop_base = asc_dvc->iop_base; ! 12198: asc_isr_callback = (ASC_ISR_CALLBACK) asc_dvc->isr_callback; ! 12199: last_int_level = DvcEnterCritical(); ! 12200: scsiq = (ASC_QDONE_INFO *) & scsiq_buf; ! 12201: for (q_no = ASC_MIN_ACTIVE_QNO; q_no <= asc_dvc->max_total_qng; ! 12202: q_no++) { ! 12203: q_addr = ASC_QNO_TO_QADDR(q_no); ! 12204: _AscCopyLramScsiDoneQ(iop_base, q_addr, scsiq, asc_dvc->max_dma_count); ! 12205: if (((scsiq->q_status & QS_READY) != 0) && ! 12206: ((scsiq->q_status & QS_ABORTED) == 0) && ! 12207: ((scsiq->cntl & QCSG_SG_XFER_LIST) == 0)) { ! 12208: if (scsiq->d2.target_ix == target_ix) { ! 12209: scsiq->q_status |= QS_ABORTED; ! 12210: scsiq->d3.done_stat = QD_ABORTED_BY_HOST; ! 12211: AscWriteLramDWord(iop_base, ! 12212: (ushort) (q_addr + (ushort) ASC_SCSIQ_D_SRBPTR), ! 12213: 0L); ! 12214: AscWriteLramByte(iop_base, ! 12215: (ushort) (q_addr + (ushort) ASC_SCSIQ_B_STATUS), ! 12216: scsiq->q_status); ! 12217: (*asc_isr_callback) (asc_dvc, scsiq); ! 12218: } ! 12219: } ! 12220: } ! 12221: DvcLeaveCritical(last_int_level); ! 12222: return (1); ! 12223: } ! 12224: #endif /* version >= v1.3.89 */ ! 12225: ! 12226: STATIC int ! 12227: AscHostReqRiscHalt( ! 12228: PortAddr iop_base ! 12229: ) ! 12230: { ! 12231: int count = 0; ! 12232: int sta = 0; ! 12233: uchar saved_stop_code; ! 12234: ! 12235: if (AscIsChipHalted(iop_base)) ! 12236: return (1); ! 12237: saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); ! 12238: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, ! 12239: ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP ! 12240: ); ! 12241: do { ! 12242: if (AscIsChipHalted(iop_base)) { ! 12243: sta = 1; ! 12244: break; ! 12245: } ! 12246: DvcSleepMilliSecond(100); ! 12247: } while (count++ < 20); ! 12248: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code); ! 12249: return (sta); ! 12250: } ! 12251: ! 12252: STATIC int ! 12253: AscStopQueueExe( ! 12254: PortAddr iop_base ! 12255: ) ! 12256: { ! 12257: int count = 0; ! 12258: ! 12259: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) { ! 12260: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, ! 12261: ASC_STOP_REQ_RISC_STOP); ! 12262: do { ! 12263: if ( ! 12264: AscReadLramByte(iop_base, ASCV_STOP_CODE_B) & ! 12265: ASC_STOP_ACK_RISC_STOP) { ! 12266: return (1); ! 12267: } ! 12268: DvcSleepMilliSecond(100); ! 12269: } while (count++ < 20); ! 12270: } ! 12271: return (0); ! 12272: } ! 12273: ! 12274: STATIC int ! 12275: AscStartQueueExe( ! 12276: PortAddr iop_base ! 12277: ) ! 12278: { ! 12279: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) { ! 12280: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0); ! 12281: } ! 12282: return (1); ! 12283: } ! 12284: ! 12285: STATIC int ! 12286: AscCleanUpBusyQueue( ! 12287: PortAddr iop_base ! 12288: ) ! 12289: { ! 12290: int count; ! 12291: uchar stop_code; ! 12292: ! 12293: count = 0; ! 12294: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) { ! 12295: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, ! 12296: ASC_STOP_CLEAN_UP_BUSY_Q); ! 12297: do { ! 12298: stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); ! 12299: if ((stop_code & ASC_STOP_CLEAN_UP_BUSY_Q) == 0) ! 12300: break; ! 12301: DvcSleepMilliSecond(100); ! 12302: } while (count++ < 20); ! 12303: } ! 12304: return (1); ! 12305: } ! 12306: ! 12307: #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89) ! 12308: STATIC int ! 12309: AscCleanUpDiscQueue( ! 12310: PortAddr iop_base ! 12311: ) ! 12312: { ! 12313: int count; ! 12314: uchar stop_code; ! 12315: ! 12316: count = 0; ! 12317: if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) != 0) { ! 12318: AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, ! 12319: ASC_STOP_CLEAN_UP_DISC_Q); ! 12320: do { ! 12321: stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); ! 12322: if ((stop_code & ASC_STOP_CLEAN_UP_DISC_Q) == 0) ! 12323: break; ! 12324: DvcSleepMilliSecond(100); ! 12325: } while (count++ < 20); ! 12326: } ! 12327: return (1); ! 12328: } ! 12329: #endif /* version >= v1.3.89 */ ! 12330: ! 12331: STATIC int ! 12332: AscWaitTixISRDone( ! 12333: ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 12334: uchar target_ix ! 12335: ) ! 12336: { ! 12337: uchar cur_req; ! 12338: uchar tid_no; ! 12339: int i = 0; ! 12340: ! 12341: tid_no = ASC_TIX_TO_TID(target_ix); ! 12342: while (i++ < 10) { ! 12343: if ((cur_req = asc_dvc->cur_dvc_qng[tid_no]) == 0) { ! 12344: break; ! 12345: } ! 12346: DvcSleepMilliSecond(1000L); ! 12347: if (asc_dvc->cur_dvc_qng[tid_no] == cur_req) { ! 12348: break; ! 12349: } ! 12350: } ! 12351: return (1); ! 12352: } ! 12353: ! 12354: STATIC int ! 12355: AscWaitISRDone( ! 12356: REG ASC_DVC_VAR asc_ptr_type * asc_dvc ! 12357: ) ! 12358: { ! 12359: int tid; ! 12360: ! 12361: for (tid = 0; tid <= ASC_MAX_TID; tid++) { ! 12362: AscWaitTixISRDone(asc_dvc, ASC_TID_TO_TIX(tid)); ! 12363: } ! 12364: return (1); ! 12365: } ! 12366: ! 12367: STATIC ulong ! 12368: AscGetOnePhyAddr( ! 12369: REG ASC_DVC_VAR asc_ptr_type * asc_dvc, ! 12370: uchar * buf_addr, ! 12371: ulong buf_size ! 12372: ) ! 12373: { ! 12374: ASC_MIN_SG_HEAD sg_head; ! 12375: ! 12376: sg_head.entry_cnt = ASC_MIN_SG_LIST; ! 12377: if (DvcGetSGList(asc_dvc, (uchar *) buf_addr, ! 12378: buf_size, (ASC_SG_HEAD *) & sg_head) != buf_size) { ! 12379: return (0L); ! 12380: } ! 12381: if (sg_head.entry_cnt > 1) { ! 12382: return (0L); ! 12383: } ! 12384: return (sg_head.sg_list[0].addr); ! 12385: } ! 12386: ! 12387: STATIC void ! 12388: DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec) ! 12389: { ! 12390: udelay(micro_sec); ! 12391: } ! 12392: ! 12393: STATIC void ! 12394: DvcDelayNanoSecond(ASC_DVC_VAR asc_ptr_type * asc_dvc, ulong nano_sec) ! 12395: { ! 12396: udelay((nano_sec + 999)/1000); ! 12397: } ! 12398: ! 12399: ASC_INITFUNC( ! 12400: STATIC ulong ! 12401: AscGetEisaProductID( ! 12402: PortAddr iop_base ! 12403: ) ! 12404: ) ! 12405: { ! 12406: PortAddr eisa_iop; ! 12407: ushort product_id_high, product_id_low; ! 12408: ulong product_id; ! 12409: ! 12410: eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK; ! 12411: product_id_low = inpw(eisa_iop); ! 12412: product_id_high = inpw(eisa_iop + 2); ! 12413: product_id = ((ulong) product_id_high << 16) | (ulong) product_id_low; ! 12414: return (product_id); ! 12415: } ! 12416: ! 12417: ASC_INITFUNC( ! 12418: STATIC PortAddr ! 12419: AscSearchIOPortAddrEISA( ! 12420: PortAddr iop_base ! 12421: ) ! 12422: ) ! 12423: { ! 12424: ulong eisa_product_id; ! 12425: ! 12426: if (iop_base == 0) { ! 12427: iop_base = ASC_EISA_MIN_IOP_ADDR; ! 12428: } else { ! 12429: if (iop_base == ASC_EISA_MAX_IOP_ADDR) ! 12430: return (0); ! 12431: if ((iop_base & 0x0050) == 0x0050) { ! 12432: iop_base += ASC_EISA_BIG_IOP_GAP; ! 12433: } else { ! 12434: iop_base += ASC_EISA_SMALL_IOP_GAP; ! 12435: } ! 12436: } ! 12437: while (iop_base <= ASC_EISA_MAX_IOP_ADDR) { ! 12438: eisa_product_id = AscGetEisaProductID(iop_base); ! 12439: if ((eisa_product_id == ASC_EISA_ID_740) || ! 12440: (eisa_product_id == ASC_EISA_ID_750)) { ! 12441: if (AscFindSignature(iop_base)) { ! 12442: inpw(iop_base + 4); ! 12443: return (iop_base); ! 12444: } ! 12445: } ! 12446: if (iop_base == ASC_EISA_MAX_IOP_ADDR) ! 12447: return (0); ! 12448: if ((iop_base & 0x0050) == 0x0050) { ! 12449: iop_base += ASC_EISA_BIG_IOP_GAP; ! 12450: } else { ! 12451: iop_base += ASC_EISA_SMALL_IOP_GAP; ! 12452: } ! 12453: } ! 12454: return (0); ! 12455: } ! 12456: ! 12457: STATIC int ! 12458: AscStartChip( ! 12459: PortAddr iop_base ! 12460: ) ! 12461: { ! 12462: AscSetChipControl(iop_base, 0); ! 12463: if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { ! 12464: return (0); ! 12465: } ! 12466: return (1); ! 12467: } ! 12468: ! 12469: STATIC int ! 12470: AscStopChip( ! 12471: PortAddr iop_base ! 12472: ) ! 12473: { ! 12474: uchar cc_val; ! 12475: ! 12476: cc_val = AscGetChipControl(iop_base) & (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG)); ! 12477: AscSetChipControl(iop_base, (uchar) (cc_val | CC_HALT)); ! 12478: AscSetChipIH(iop_base, INS_HALT); ! 12479: AscSetChipIH(iop_base, INS_RFLAG_WTM); ! 12480: if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) { ! 12481: return (0); ! 12482: } ! 12483: return (1); ! 12484: } ! 12485: ! 12486: STATIC int ! 12487: AscIsChipHalted( ! 12488: PortAddr iop_base ! 12489: ) ! 12490: { ! 12491: if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { ! 12492: if ((AscGetChipControl(iop_base) & CC_HALT) != 0) { ! 12493: return (1); ! 12494: } ! 12495: } ! 12496: return (0); ! 12497: } ! 12498: ! 12499: STATIC void ! 12500: AscSetChipIH( ! 12501: PortAddr iop_base, ! 12502: ushort ins_code ! 12503: ) ! 12504: { ! 12505: AscSetBank(iop_base, 1); ! 12506: AscWriteChipIH(iop_base, ins_code); ! 12507: AscSetBank(iop_base, 0); ! 12508: return; ! 12509: } ! 12510: ! 12511: STATIC void ! 12512: AscAckInterrupt( ! 12513: PortAddr iop_base ! 12514: ) ! 12515: { ! 12516: uchar host_flag; ! 12517: uchar risc_flag; ! 12518: ushort loop; ! 12519: ! 12520: loop = 0; ! 12521: do { ! 12522: risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B); ! 12523: if (loop++ > 0x7FFF) { ! 12524: break; ! 12525: } ! 12526: } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0); ! 12527: host_flag = AscReadLramByte(iop_base, ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT); ! 12528: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, ! 12529: (uchar) (host_flag | ASC_HOST_FLAG_ACK_INT)); ! 12530: AscSetChipStatus(iop_base, CIW_INT_ACK); ! 12531: loop = 0; ! 12532: while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) { ! 12533: AscSetChipStatus(iop_base, CIW_INT_ACK); ! 12534: if (loop++ > 3) { ! 12535: break; ! 12536: } ! 12537: } ! 12538: AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); ! 12539: return; ! 12540: } ! 12541: ! 12542: STATIC void ! 12543: AscDisableInterrupt( ! 12544: PortAddr iop_base ! 12545: ) ! 12546: { ! 12547: ushort cfg; ! 12548: ! 12549: cfg = AscGetChipCfgLsw(iop_base); ! 12550: AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON)); ! 12551: return; ! 12552: } ! 12553: ! 12554: STATIC void ! 12555: AscEnableInterrupt( ! 12556: PortAddr iop_base ! 12557: ) ! 12558: { ! 12559: ushort cfg; ! 12560: ! 12561: cfg = AscGetChipCfgLsw(iop_base); ! 12562: AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON); ! 12563: return; ! 12564: } ! 12565: ! 12566: ! 12567: ! 12568: STATIC void ! 12569: AscSetBank( ! 12570: PortAddr iop_base, ! 12571: uchar bank ! 12572: ) ! 12573: { ! 12574: uchar val; ! 12575: ! 12576: val = AscGetChipControl(iop_base) & ! 12577: (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | CC_CHIP_RESET)); ! 12578: if (bank == 1) { ! 12579: val |= CC_BANK_ONE; ! 12580: } else if (bank == 2) { ! 12581: val |= CC_DIAG | CC_BANK_ONE; ! 12582: } else { ! 12583: val &= ~CC_BANK_ONE; ! 12584: } ! 12585: AscSetChipControl(iop_base, val); ! 12586: return; ! 12587: } ! 12588: ! 12589: STATIC int ! 12590: AscResetChipAndScsiBus( ! 12591: ASC_DVC_VAR *asc_dvc ! 12592: ) ! 12593: { ! 12594: PortAddr iop_base; ! 12595: ! 12596: iop_base = asc_dvc->iop_base; ! 12597: while (AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) ; ! 12598: AscStopChip(iop_base); ! 12599: AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT); ! 12600: DvcDelayNanoSecond(asc_dvc, 60000); ! 12601: AscSetChipIH(iop_base, INS_RFLAG_WTM); ! 12602: AscSetChipIH(iop_base, INS_HALT); ! 12603: AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT); ! 12604: AscSetChipControl(iop_base, CC_HALT); ! 12605: DvcSleepMilliSecond(200); ! 12606: AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); ! 12607: AscSetChipStatus(iop_base, 0); ! 12608: return (AscIsChipHalted(iop_base)); ! 12609: } ! 12610: ! 12611: ASC_INITFUNC( ! 12612: STATIC ulong ! 12613: AscGetMaxDmaCount( ! 12614: ushort bus_type ! 12615: ) ! 12616: ) ! 12617: { ! 12618: if (bus_type & ASC_IS_ISA) ! 12619: return (ASC_MAX_ISA_DMA_COUNT); ! 12620: else if (bus_type & (ASC_IS_EISA | ASC_IS_VL)) ! 12621: return (ASC_MAX_VL_DMA_COUNT); ! 12622: return (ASC_MAX_PCI_DMA_COUNT); ! 12623: } ! 12624: ! 12625: ASC_INITFUNC( ! 12626: STATIC ushort ! 12627: AscGetIsaDmaChannel( ! 12628: PortAddr iop_base ! 12629: ) ! 12630: ) ! 12631: { ! 12632: ushort channel; ! 12633: ! 12634: channel = AscGetChipCfgLsw(iop_base) & 0x0003; ! 12635: if (channel == 0x03) ! 12636: return (0); ! 12637: else if (channel == 0x00) ! 12638: return (7); ! 12639: return (channel + 4); ! 12640: } ! 12641: ! 12642: ASC_INITFUNC( ! 12643: STATIC ushort ! 12644: AscSetIsaDmaChannel( ! 12645: PortAddr iop_base, ! 12646: ushort dma_channel ! 12647: ) ! 12648: ) ! 12649: { ! 12650: ushort cfg_lsw; ! 12651: uchar value; ! 12652: ! 12653: if ((dma_channel >= 5) && (dma_channel <= 7)) { ! 12654: if (dma_channel == 7) ! 12655: value = 0x00; ! 12656: else ! 12657: value = dma_channel - 4; ! 12658: cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC; ! 12659: cfg_lsw |= value; ! 12660: AscSetChipCfgLsw(iop_base, cfg_lsw); ! 12661: return (AscGetIsaDmaChannel(iop_base)); ! 12662: } ! 12663: return (0); ! 12664: } ! 12665: ! 12666: ASC_INITFUNC( ! 12667: STATIC uchar ! 12668: AscSetIsaDmaSpeed( ! 12669: PortAddr iop_base, ! 12670: uchar speed_value ! 12671: ) ! 12672: ) ! 12673: { ! 12674: speed_value &= 0x07; ! 12675: AscSetBank(iop_base, 1); ! 12676: AscWriteChipDmaSpeed(iop_base, speed_value); ! 12677: AscSetBank(iop_base, 0); ! 12678: return (AscGetIsaDmaSpeed(iop_base)); ! 12679: } ! 12680: ! 12681: ASC_INITFUNC( ! 12682: STATIC uchar ! 12683: AscGetIsaDmaSpeed( ! 12684: PortAddr iop_base ! 12685: ) ! 12686: ) ! 12687: { ! 12688: uchar speed_value; ! 12689: ! 12690: AscSetBank(iop_base, 1); ! 12691: speed_value = AscReadChipDmaSpeed(iop_base); ! 12692: speed_value &= 0x07; ! 12693: AscSetBank(iop_base, 0); ! 12694: return (speed_value); ! 12695: } ! 12696: ! 12697: ASC_INITFUNC( ! 12698: STATIC ushort ! 12699: AscReadPCIConfigWord( ! 12700: ASC_DVC_VAR asc_ptr_type *asc_dvc, ! 12701: ushort pci_config_offset) ! 12702: ) ! 12703: { ! 12704: uchar lsb, msb; ! 12705: ! 12706: lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset); ! 12707: msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1); ! 12708: return ((ushort) ((msb << 8) | lsb)); ! 12709: } ! 12710: ! 12711: ASC_INITFUNC( ! 12712: STATIC ushort ! 12713: AscInitGetConfig( ! 12714: ASC_DVC_VAR asc_ptr_type * asc_dvc ! 12715: ) ! 12716: ) ! 12717: { ! 12718: ushort warn_code; ! 12719: PortAddr iop_base; ! 12720: ushort PCIDeviceID; ! 12721: ushort PCIVendorID; ! 12722: uchar PCIRevisionID; ! 12723: uchar prevCmdRegBits; ! 12724: ! 12725: warn_code = 0; ! 12726: iop_base = asc_dvc->iop_base; ! 12727: asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG; ! 12728: if (asc_dvc->err_code != 0) { ! 12729: return (UW_ERR); ! 12730: } ! 12731: if (asc_dvc->bus_type == ASC_IS_PCI) { ! 12732: PCIVendorID = AscReadPCIConfigWord(asc_dvc, ! 12733: AscPCIConfigVendorIDRegister); ! 12734: ! 12735: PCIDeviceID = AscReadPCIConfigWord(asc_dvc, ! 12736: AscPCIConfigDeviceIDRegister); ! 12737: ! 12738: PCIRevisionID = DvcReadPCIConfigByte(asc_dvc, ! 12739: AscPCIConfigRevisionIDRegister); ! 12740: ! 12741: if (PCIVendorID != ASC_PCI_VENDORID) { ! 12742: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; ! 12743: } ! 12744: prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc, ! 12745: AscPCIConfigCommandRegister); ! 12746: ! 12747: if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) != ! 12748: AscPCICmdRegBits_IOMemBusMaster) { ! 12749: DvcWritePCIConfigByte(asc_dvc, ! 12750: AscPCIConfigCommandRegister, ! 12751: (prevCmdRegBits | ! 12752: AscPCICmdRegBits_IOMemBusMaster)); ! 12753: ! 12754: if ((DvcReadPCIConfigByte(asc_dvc, ! 12755: AscPCIConfigCommandRegister) ! 12756: & AscPCICmdRegBits_IOMemBusMaster) ! 12757: != AscPCICmdRegBits_IOMemBusMaster) { ! 12758: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; ! 12759: } ! 12760: } ! 12761: if ((PCIDeviceID == ASC_PCI_DEVICEID_1200A) || ! 12762: (PCIDeviceID == ASC_PCI_DEVICEID_1200B)) { ! 12763: DvcWritePCIConfigByte(asc_dvc, ! 12764: AscPCIConfigLatencyTimer, 0x00); ! 12765: if (DvcReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) ! 12766: != 0x00) { ! 12767: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; ! 12768: } ! 12769: } else if (PCIDeviceID == ASC_PCI_DEVICEID_ULTRA) { ! 12770: if (DvcReadPCIConfigByte(asc_dvc, ! 12771: AscPCIConfigLatencyTimer) < 0x20) { ! 12772: DvcWritePCIConfigByte(asc_dvc, ! 12773: AscPCIConfigLatencyTimer, 0x20); ! 12774: ! 12775: if (DvcReadPCIConfigByte(asc_dvc, ! 12776: AscPCIConfigLatencyTimer) < 0x20) { ! 12777: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; ! 12778: } ! 12779: } ! 12780: } ! 12781: } ! 12782: ! 12783: if (AscFindSignature(iop_base)) { ! 12784: warn_code |= AscInitAscDvcVar(asc_dvc); ! 12785: warn_code |= AscInitFromEEP(asc_dvc); ! 12786: asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG; ! 12787: if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) { ! 12788: asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT; ! 12789: } ! 12790: } else { ! 12791: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; ! 12792: } ! 12793: return(warn_code); ! 12794: } ! 12795: ! 12796: ASC_INITFUNC( ! 12797: STATIC ushort ! 12798: AscInitSetConfig( ! 12799: ASC_DVC_VAR asc_ptr_type * asc_dvc ! 12800: ) ! 12801: ) ! 12802: { ! 12803: ushort warn_code = 0; ! 12804: ! 12805: asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG; ! 12806: if (asc_dvc->err_code != 0) ! 12807: return (UW_ERR); ! 12808: if (AscFindSignature(asc_dvc->iop_base)) { ! 12809: warn_code |= AscInitFromAscDvcVar(asc_dvc); ! 12810: asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG; ! 12811: } else { ! 12812: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; ! 12813: } ! 12814: return (warn_code); ! 12815: } ! 12816: ! 12817: ASC_INITFUNC( ! 12818: STATIC ushort ! 12819: AscInitFromAscDvcVar( ! 12820: ASC_DVC_VAR asc_ptr_type * asc_dvc ! 12821: ) ! 12822: ) ! 12823: { ! 12824: PortAddr iop_base; ! 12825: ushort cfg_msw; ! 12826: ushort warn_code; ! 12827: ushort pci_device_id; ! 12828: ! 12829: iop_base = asc_dvc->iop_base; ! 12830: pci_device_id = asc_dvc->cfg->pci_device_id; ! 12831: warn_code = 0; ! 12832: cfg_msw = AscGetChipCfgMsw(iop_base); ! 12833: if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { ! 12834: cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); ! 12835: warn_code |= ASC_WARN_CFG_MSW_RECOVER; ! 12836: AscSetChipCfgMsw(iop_base, cfg_msw); ! 12837: } ! 12838: if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) != ! 12839: asc_dvc->cfg->cmd_qng_enabled) { ! 12840: asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled; ! 12841: warn_code |= ASC_WARN_CMD_QNG_CONFLICT; ! 12842: } ! 12843: if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { ! 12844: warn_code |= ASC_WARN_AUTO_CONFIG; ! 12845: } ! 12846: if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) { ! 12847: if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type) ! 12848: != asc_dvc->irq_no) { ! 12849: asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO; ! 12850: } ! 12851: } ! 12852: if (asc_dvc->bus_type & ASC_IS_PCI) { ! 12853: cfg_msw &= 0xFFC0; ! 12854: AscSetChipCfgMsw(iop_base, cfg_msw); ! 12855: if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) { ! 12856: } else { ! 12857: if ((pci_device_id == ASC_PCI_DEVICE_ID_REV_A) || ! 12858: (pci_device_id == ASC_PCI_DEVICE_ID_REV_B)) { ! 12859: asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB; ! 12860: asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN; ! 12861: } ! 12862: } ! 12863: } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) { ! 12864: if (AscGetChipVersion(iop_base, asc_dvc->bus_type) ! 12865: == ASC_CHIP_VER_ASYN_BUG) { ! 12866: asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN; ! 12867: } ! 12868: } ! 12869: if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) != ! 12870: asc_dvc->cfg->chip_scsi_id) { ! 12871: asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID; ! 12872: } ! 12873: if (asc_dvc->bus_type & ASC_IS_ISA) { ! 12874: AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel); ! 12875: AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed); ! 12876: } ! 12877: return (warn_code); ! 12878: } ! 12879: ! 12880: ASC_INITFUNC( ! 12881: STATIC ushort ! 12882: AscInitAsc1000Driver( ! 12883: ASC_DVC_VAR asc_ptr_type * asc_dvc ! 12884: ) ! 12885: ) ! 12886: { ! 12887: ushort warn_code; ! 12888: PortAddr iop_base; ! 12889: extern ushort _asc_mcode_size; ! 12890: extern ulong _asc_mcode_chksum; ! 12891: extern uchar _asc_mcode_buf[]; ! 12892: ! 12893: iop_base = asc_dvc->iop_base; ! 12894: warn_code = 0; ! 12895: if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) && ! 12896: !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) { ! 12897: AscResetChipAndScsiBus(asc_dvc); ! 12898: DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000)); ! 12899: } ! 12900: asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC; ! 12901: if (asc_dvc->err_code != 0) ! 12902: return (UW_ERR); ! 12903: if (!AscFindSignature(asc_dvc->iop_base)) { ! 12904: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; ! 12905: return (warn_code); ! 12906: } ! 12907: AscDisableInterrupt(iop_base); ! 12908: warn_code |= AscInitLram(asc_dvc); ! 12909: if (asc_dvc->err_code != 0) ! 12910: return (UW_ERR); ! 12911: if (AscLoadMicroCode(iop_base, 0, (ushort *) _asc_mcode_buf, ! 12912: _asc_mcode_size) != _asc_mcode_chksum) { ! 12913: asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; ! 12914: return (warn_code); ! 12915: } ! 12916: warn_code |= AscInitMicroCodeVar(asc_dvc); ! 12917: asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; ! 12918: AscEnableInterrupt(iop_base); ! 12919: return (warn_code); ! 12920: } ! 12921: ! 12922: ASC_INITFUNC( ! 12923: STATIC ushort ! 12924: AscInitAscDvcVar( ! 12925: ASC_DVC_VAR asc_ptr_type * asc_dvc ! 12926: ) ! 12927: ) ! 12928: { ! 12929: int i; ! 12930: PortAddr iop_base; ! 12931: ushort warn_code; ! 12932: uchar chip_version; ! 12933: ! 12934: iop_base = asc_dvc->iop_base; ! 12935: warn_code = 0; ! 12936: asc_dvc->err_code = 0; ! 12937: if ((asc_dvc->bus_type & ! 12938: (ASC_IS_ISA | ASC_IS_PCI | ASC_IS_EISA | ASC_IS_VL)) == 0) { ! 12939: asc_dvc->err_code |= ASC_IERR_NO_BUS_TYPE; ! 12940: } ! 12941: AscSetChipControl(iop_base, CC_HALT); ! 12942: AscSetChipStatus(iop_base, 0); ! 12943: asc_dvc->bug_fix_cntl = 0; ! 12944: asc_dvc->pci_fix_asyn_xfer = 0; ! 12945: asc_dvc->pci_fix_asyn_xfer_always = 0; ! 12946: asc_dvc->init_state = 0; ! 12947: asc_dvc->sdtr_done = 0; ! 12948: asc_dvc->cur_total_qng = 0; ! 12949: asc_dvc->is_in_int = 0; ! 12950: asc_dvc->in_critical_cnt = 0; ! 12951: asc_dvc->last_q_shortage = 0; ! 12952: asc_dvc->use_tagged_qng = 0; ! 12953: asc_dvc->no_scam = 0; ! 12954: asc_dvc->unit_not_ready = 0; ! 12955: asc_dvc->queue_full_or_busy = 0; ! 12956: asc_dvc->redo_scam = 0 ; ! 12957: asc_dvc->res2 = 0 ; ! 12958: asc_dvc->host_init_sdtr_index = 0 ; ! 12959: asc_dvc->res7 = 0 ; ! 12960: asc_dvc->res8 = 0 ; ! 12961: asc_dvc->cfg->can_tagged_qng = 0 ; ! 12962: asc_dvc->cfg->cmd_qng_enabled = 0; ! 12963: asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL; ! 12964: asc_dvc->init_sdtr = 0; ! 12965: asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG; ! 12966: asc_dvc->scsi_reset_wait = 3; ! 12967: asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET; ! 12968: asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type); ! 12969: asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET; ! 12970: asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET; ! 12971: asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID; ! 12972: asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER; ! 12973: asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) | ! 12974: ASC_LIB_VERSION_MINOR; ! 12975: chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type); ! 12976: asc_dvc->cfg->chip_version = chip_version; ! 12977: asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0; ! 12978: asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1; ! 12979: asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2; ! 12980: asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3; ! 12981: asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4; ! 12982: asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5; ! 12983: asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6; ! 12984: asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7; ! 12985: asc_dvc->max_sdtr_index = 7; ! 12986: if ((asc_dvc->bus_type & ASC_IS_PCI) && ! 12987: (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) { ! 12988: asc_dvc->bus_type = ASC_IS_PCI_ULTRA; ! 12989: asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0; ! 12990: asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1; ! 12991: asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2; ! 12992: asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3; ! 12993: asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4; ! 12994: asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5; ! 12995: asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6; ! 12996: asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7; ! 12997: asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8; ! 12998: asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9; ! 12999: asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10; ! 13000: asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11; ! 13001: asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12; ! 13002: asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13; ! 13003: asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14; ! 13004: asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15; ! 13005: asc_dvc->max_sdtr_index = 15; ! 13006: if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) ! 13007: { ! 13008: AscSetExtraControl(iop_base, ! 13009: (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE)); ! 13010: } else if (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3050) { ! 13011: AscSetExtraControl(iop_base, ! 13012: (SEC_ACTIVE_NEGATE | SEC_ENABLE_FILTER)); ! 13013: } ! 13014: } ! 13015: if (asc_dvc->bus_type == ASC_IS_PCI) { ! 13016: AscSetExtraControl(iop_base, (SEC_ACTIVE_NEGATE | SEC_SLEW_RATE)); ! 13017: } ! 13018: ! 13019: asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED; ! 13020: if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) { ! 13021: AscSetChipIFC(iop_base, IFC_INIT_DEFAULT); ! 13022: asc_dvc->bus_type = ASC_IS_ISAPNP; ! 13023: } ! 13024: if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) { ! 13025: asc_dvc->cfg->isa_dma_channel = (uchar) AscGetIsaDmaChannel(iop_base); ! 13026: } ! 13027: for (i = 0; i <= ASC_MAX_TID; i++) { ! 13028: asc_dvc->cur_dvc_qng[i] = 0; ! 13029: asc_dvc->max_dvc_qng[i] = ASC_MAX_SCSI1_QNG; ! 13030: asc_dvc->scsiq_busy_head[i] = (ASC_SCSI_Q *) 0L; ! 13031: asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *) 0L; ! 13032: asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG; ! 13033: } ! 13034: return (warn_code); ! 13035: } ! 13036: ! 13037: ASC_INITFUNC( ! 13038: STATIC ushort ! 13039: AscInitFromEEP( ! 13040: ASC_DVC_VAR asc_ptr_type * asc_dvc ! 13041: ) ! 13042: ) ! 13043: { ! 13044: ASCEEP_CONFIG eep_config_buf; ! 13045: ASCEEP_CONFIG *eep_config; ! 13046: PortAddr iop_base; ! 13047: ushort chksum; ! 13048: ushort warn_code; ! 13049: ushort cfg_msw, cfg_lsw; ! 13050: int i; ! 13051: int write_eep = 0; ! 13052: ! 13053: iop_base = asc_dvc->iop_base; ! 13054: warn_code = 0; ! 13055: AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE); ! 13056: AscStopQueueExe(iop_base); ! 13057: if ((AscStopChip(iop_base) == FALSE) || ! 13058: (AscGetChipScsiCtrl(iop_base) != 0)) { ! 13059: asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE; ! 13060: AscResetChipAndScsiBus(asc_dvc); ! 13061: DvcSleepMilliSecond((ulong) ((ushort) asc_dvc->scsi_reset_wait * 1000)); ! 13062: } ! 13063: if (AscIsChipHalted(iop_base) == FALSE) { ! 13064: asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; ! 13065: return (warn_code); ! 13066: } ! 13067: AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); ! 13068: if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { ! 13069: asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; ! 13070: return (warn_code); ! 13071: } ! 13072: eep_config = (ASCEEP_CONFIG *) & eep_config_buf; ! 13073: cfg_msw = AscGetChipCfgMsw(iop_base); ! 13074: cfg_lsw = AscGetChipCfgLsw(iop_base); ! 13075: if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { ! 13076: cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); ! 13077: warn_code |= ASC_WARN_CFG_MSW_RECOVER; ! 13078: AscSetChipCfgMsw(iop_base, cfg_msw); ! 13079: } ! 13080: chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type); ! 13081: if (chksum == 0) { ! 13082: chksum = 0xaa55; ! 13083: } ! 13084: if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { ! 13085: warn_code |= ASC_WARN_AUTO_CONFIG; ! 13086: if (asc_dvc->cfg->chip_version == 3) { ! 13087: if (eep_config->cfg_lsw != cfg_lsw) { ! 13088: warn_code |= ASC_WARN_EEPROM_RECOVER; ! 13089: eep_config->cfg_lsw = AscGetChipCfgLsw(iop_base); ! 13090: } ! 13091: if (eep_config->cfg_msw != cfg_msw) { ! 13092: warn_code |= ASC_WARN_EEPROM_RECOVER; ! 13093: eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); ! 13094: } ! 13095: } ! 13096: } ! 13097: eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; ! 13098: eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON; ! 13099: if (chksum != eep_config->chksum) { ! 13100: if (AscGetChipVersion(iop_base, asc_dvc->bus_type) == ! 13101: ASC_CHIP_VER_PCI_ULTRA_3050 ) ! 13102: { ! 13103: eep_config->init_sdtr = 0xFF; ! 13104: eep_config->disc_enable = 0xFF; ! 13105: eep_config->start_motor = 0xFF; ! 13106: eep_config->use_cmd_qng = 0; ! 13107: eep_config->max_total_qng = 0xF0; ! 13108: eep_config->max_tag_qng = 0x20; ! 13109: eep_config->cntl = 0xBFFF; ! 13110: eep_config->chip_scsi_id = 7; ! 13111: eep_config->no_scam = 0; ! 13112: eep_config->adapter_info[0] = 0; ! 13113: eep_config->adapter_info[1] = 0; ! 13114: eep_config->adapter_info[2] = 0; ! 13115: eep_config->adapter_info[3] = 0; ! 13116: eep_config->adapter_info[4] = 0; ! 13117: /* Indicate EEPROM-less board. */ ! 13118: eep_config->adapter_info[5] = 0xBB; ! 13119: } else { ! 13120: write_eep = 1 ; ! 13121: warn_code |= ASC_WARN_EEPROM_CHKSUM ; ! 13122: } ! 13123: } ! 13124: asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr ; ! 13125: asc_dvc->cfg->disc_enable = eep_config->disc_enable; ! 13126: asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng; ! 13127: asc_dvc->cfg->isa_dma_speed = eep_config->isa_dma_speed; ! 13128: asc_dvc->start_motor = eep_config->start_motor; ! 13129: asc_dvc->dvc_cntl = eep_config->cntl; ! 13130: asc_dvc->no_scam = eep_config->no_scam; ! 13131: asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0]; ! 13132: asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1]; ! 13133: asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2]; ! 13134: asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3]; ! 13135: asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4]; ! 13136: asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5]; ! 13137: if (!AscTestExternalLram(asc_dvc)) { ! 13138: if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA)) { ! 13139: eep_config->max_total_qng = ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG; ! 13140: eep_config->max_tag_qng = ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG; ! 13141: } else { ! 13142: eep_config->cfg_msw |= 0x0800; ! 13143: cfg_msw |= 0x0800; ! 13144: AscSetChipCfgMsw(iop_base, cfg_msw); ! 13145: eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG; ! 13146: eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG; ! 13147: } ! 13148: } else { ! 13149: } ! 13150: if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) { ! 13151: eep_config->max_total_qng = ASC_MIN_TOTAL_QNG; ! 13152: } ! 13153: if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) { ! 13154: eep_config->max_total_qng = ASC_MAX_TOTAL_QNG; ! 13155: } ! 13156: if (eep_config->max_tag_qng > eep_config->max_total_qng) { ! 13157: eep_config->max_tag_qng = eep_config->max_total_qng; ! 13158: } ! 13159: if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) { ! 13160: eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC; ! 13161: } ! 13162: asc_dvc->max_total_qng = eep_config->max_total_qng; ! 13163: if ((eep_config->use_cmd_qng & eep_config->disc_enable) != ! 13164: eep_config->use_cmd_qng) { ! 13165: eep_config->disc_enable = eep_config->use_cmd_qng; ! 13166: warn_code |= ASC_WARN_CMD_QNG_CONFLICT; ! 13167: } ! 13168: if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) { ! 13169: asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type); ! 13170: } ! 13171: eep_config->chip_scsi_id &= ASC_MAX_TID; ! 13172: asc_dvc->cfg->chip_scsi_id = eep_config->chip_scsi_id; ! 13173: if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) && ! 13174: !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) { ! 13175: asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX; ! 13176: } ! 13177: ! 13178: for (i = 0; i <= ASC_MAX_TID; i++) { ! 13179: asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i]; ! 13180: asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng; ! 13181: asc_dvc->cfg->sdtr_period_offset[i] = ! 13182: (uchar) (ASC_DEF_SDTR_OFFSET | ! 13183: (asc_dvc->host_init_sdtr_index << 4)); ! 13184: } ! 13185: eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); ! 13186: if (write_eep) { ! 13187: (void) AscSetEEPConfig(iop_base, eep_config, asc_dvc->bus_type); ! 13188: } ! 13189: return (warn_code); ! 13190: } ! 13191: ! 13192: ASC_INITFUNC( ! 13193: STATIC ushort ! 13194: AscInitMicroCodeVar( ! 13195: ASC_DVC_VAR asc_ptr_type * asc_dvc ! 13196: ) ! 13197: ) ! 13198: { ! 13199: int i; ! 13200: ushort warn_code; ! 13201: PortAddr iop_base; ! 13202: ulong phy_addr; ! 13203: ! 13204: iop_base = asc_dvc->iop_base; ! 13205: warn_code = 0; ! 13206: for (i = 0; i <= ASC_MAX_TID; i++) { ! 13207: AscPutMCodeInitSDTRAtID(iop_base, i, ! 13208: asc_dvc->cfg->sdtr_period_offset[i] ! 13209: ); ! 13210: } ! 13211: AscInitQLinkVar(asc_dvc); ! 13212: AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, ! 13213: asc_dvc->cfg->disc_enable); ! 13214: AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B, ! 13215: ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id)); ! 13216: if ((phy_addr = AscGetOnePhyAddr(asc_dvc, ! 13217: (uchar *) asc_dvc->cfg->overrun_buf, ! 13218: ASC_OVERRUN_BSIZE)) == 0L) { ! 13219: asc_dvc->err_code |= ASC_IERR_GET_PHY_ADDR; ! 13220: } else { ! 13221: phy_addr = (phy_addr & 0xFFFFFFF8UL) + 8; ! 13222: AscWriteLramDWord(iop_base, ASCV_OVERRUN_PADDR_D, phy_addr); ! 13223: AscWriteLramDWord(iop_base, ASCV_OVERRUN_BSIZE_D, ! 13224: ASC_OVERRUN_BSIZE - 8); ! 13225: } ! 13226: asc_dvc->cfg->mcode_date = AscReadLramWord(iop_base, ! 13227: (ushort) ASCV_MC_DATE_W); ! 13228: asc_dvc->cfg->mcode_version = AscReadLramWord(iop_base, ! 13229: (ushort) ASCV_MC_VER_W); ! 13230: AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); ! 13231: if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { ! 13232: asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; ! 13233: return (warn_code); ! 13234: } ! 13235: if (AscStartChip(iop_base) != 1) { ! 13236: asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; ! 13237: return (warn_code); ! 13238: } ! 13239: return (warn_code); ! 13240: } ! 13241: ! 13242: ASC_INITFUNC( ! 13243: STATIC int ! 13244: AscTestExternalLram( ! 13245: ASC_DVC_VAR asc_ptr_type * asc_dvc ! 13246: ) ! 13247: ) ! 13248: { ! 13249: PortAddr iop_base; ! 13250: ushort q_addr; ! 13251: ushort saved_word; ! 13252: int sta; ! 13253: ! 13254: iop_base = asc_dvc->iop_base; ! 13255: sta = 0; ! 13256: q_addr = ASC_QNO_TO_QADDR(241); ! 13257: saved_word = AscReadLramWord(iop_base, q_addr); ! 13258: AscSetChipLramAddr(iop_base, q_addr); ! 13259: AscSetChipLramData(iop_base, 0x55AA); ! 13260: DvcSleepMilliSecond(10); ! 13261: AscSetChipLramAddr(iop_base, q_addr); ! 13262: if (AscGetChipLramData(iop_base) == 0x55AA) { ! 13263: sta = 1; ! 13264: AscWriteLramWord(iop_base, q_addr, saved_word); ! 13265: } ! 13266: return (sta); ! 13267: } ! 13268: ! 13269: ASC_INITFUNC( ! 13270: STATIC int ! 13271: AscWriteEEPCmdReg( ! 13272: PortAddr iop_base, ! 13273: uchar cmd_reg ! 13274: ) ! 13275: ) ! 13276: { ! 13277: uchar read_back; ! 13278: int retry; ! 13279: ! 13280: retry = 0; ! 13281: while (TRUE) { ! 13282: AscSetChipEEPCmd(iop_base, cmd_reg); ! 13283: DvcSleepMilliSecond(1); ! 13284: read_back = AscGetChipEEPCmd(iop_base); ! 13285: if (read_back == cmd_reg) { ! 13286: return (1); ! 13287: } ! 13288: if (retry++ > ASC_EEP_MAX_RETRY) { ! 13289: return (0); ! 13290: } ! 13291: } ! 13292: } ! 13293: ! 13294: ASC_INITFUNC( ! 13295: STATIC int ! 13296: AscWriteEEPDataReg( ! 13297: PortAddr iop_base, ! 13298: ushort data_reg ! 13299: ) ! 13300: ) ! 13301: { ! 13302: ushort read_back; ! 13303: int retry; ! 13304: ! 13305: retry = 0; ! 13306: while (TRUE) { ! 13307: AscSetChipEEPData(iop_base, data_reg); ! 13308: DvcSleepMilliSecond(1); ! 13309: read_back = AscGetChipEEPData(iop_base); ! 13310: if (read_back == data_reg) { ! 13311: return (1); ! 13312: } ! 13313: if (retry++ > ASC_EEP_MAX_RETRY) { ! 13314: return (0); ! 13315: } ! 13316: } ! 13317: } ! 13318: ! 13319: ASC_INITFUNC( ! 13320: STATIC void ! 13321: AscWaitEEPRead( ! 13322: void ! 13323: ) ! 13324: ) ! 13325: { ! 13326: DvcSleepMilliSecond(1); ! 13327: return; ! 13328: } ! 13329: ! 13330: ASC_INITFUNC( ! 13331: STATIC void ! 13332: AscWaitEEPWrite( ! 13333: void ! 13334: ) ! 13335: ) ! 13336: { ! 13337: DvcSleepMilliSecond(20); ! 13338: return; ! 13339: } ! 13340: ! 13341: ASC_INITFUNC( ! 13342: STATIC ushort ! 13343: AscReadEEPWord( ! 13344: PortAddr iop_base, ! 13345: uchar addr ! 13346: ) ! 13347: ) ! 13348: { ! 13349: ushort read_wval; ! 13350: uchar cmd_reg; ! 13351: ! 13352: AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); ! 13353: AscWaitEEPRead(); ! 13354: cmd_reg = addr | ASC_EEP_CMD_READ; ! 13355: AscWriteEEPCmdReg(iop_base, cmd_reg); ! 13356: AscWaitEEPRead(); ! 13357: read_wval = AscGetChipEEPData(iop_base); ! 13358: AscWaitEEPRead(); ! 13359: return (read_wval); ! 13360: } ! 13361: ! 13362: ASC_INITFUNC( ! 13363: STATIC ushort ! 13364: AscWriteEEPWord( ! 13365: PortAddr iop_base, ! 13366: uchar addr, ! 13367: ushort word_val ! 13368: ) ! 13369: ) ! 13370: { ! 13371: ushort read_wval; ! 13372: ! 13373: read_wval = AscReadEEPWord(iop_base, addr); ! 13374: if (read_wval != word_val) { ! 13375: AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_ABLE); ! 13376: AscWaitEEPRead(); ! 13377: AscWriteEEPDataReg(iop_base, word_val); ! 13378: AscWaitEEPRead(); ! 13379: AscWriteEEPCmdReg(iop_base, ! 13380: (uchar) ((uchar) ASC_EEP_CMD_WRITE | addr)); ! 13381: AscWaitEEPWrite(); ! 13382: AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); ! 13383: AscWaitEEPRead(); ! 13384: return (AscReadEEPWord(iop_base, addr)); ! 13385: } ! 13386: return (read_wval); ! 13387: } ! 13388: ! 13389: ASC_INITFUNC( ! 13390: STATIC ushort ! 13391: AscGetEEPConfig( ! 13392: PortAddr iop_base, ! 13393: ASCEEP_CONFIG * cfg_buf, ushort bus_type ! 13394: ) ! 13395: ) ! 13396: { ! 13397: ushort wval; ! 13398: ushort sum; ! 13399: ushort *wbuf; ! 13400: int cfg_beg; ! 13401: int cfg_end; ! 13402: int s_addr; ! 13403: int isa_pnp_wsize; ! 13404: ! 13405: wbuf = (ushort *) cfg_buf; ! 13406: sum = 0; ! 13407: isa_pnp_wsize = 0; ! 13408: for (s_addr = 0; s_addr < (2 + isa_pnp_wsize); s_addr++, wbuf++) { ! 13409: wval = AscReadEEPWord(iop_base, (uchar) s_addr); ! 13410: sum += wval; ! 13411: *wbuf = wval; ! 13412: } ! 13413: if (bus_type & ASC_IS_VL) { ! 13414: cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; ! 13415: cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; ! 13416: } else { ! 13417: cfg_beg = ASC_EEP_DVC_CFG_BEG; ! 13418: cfg_end = ASC_EEP_MAX_DVC_ADDR; ! 13419: } ! 13420: for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); ! 13421: s_addr++, wbuf++) { ! 13422: wval = AscReadEEPWord(iop_base, (uchar) s_addr); ! 13423: sum += wval; ! 13424: *wbuf = wval; ! 13425: } ! 13426: *wbuf = AscReadEEPWord(iop_base, (uchar) s_addr); ! 13427: return (sum); ! 13428: } ! 13429: ! 13430: ASC_INITFUNC( ! 13431: STATIC int ! 13432: AscSetEEPConfigOnce( ! 13433: PortAddr iop_base, ! 13434: ASCEEP_CONFIG * cfg_buf, ushort bus_type ! 13435: ) ! 13436: ) ! 13437: { ! 13438: int n_error; ! 13439: ushort *wbuf; ! 13440: ushort sum; ! 13441: int s_addr; ! 13442: int cfg_beg; ! 13443: int cfg_end; ! 13444: ! 13445: wbuf = (ushort *) cfg_buf; ! 13446: n_error = 0; ! 13447: sum = 0; ! 13448: for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { ! 13449: sum += *wbuf; ! 13450: if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) { ! 13451: n_error++; ! 13452: } ! 13453: } ! 13454: if (bus_type & ASC_IS_VL) { ! 13455: cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; ! 13456: cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; ! 13457: } else { ! 13458: cfg_beg = ASC_EEP_DVC_CFG_BEG; ! 13459: cfg_end = ASC_EEP_MAX_DVC_ADDR; ! 13460: } ! 13461: for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); ! 13462: s_addr++, wbuf++) { ! 13463: sum += *wbuf; ! 13464: if (*wbuf != AscWriteEEPWord(iop_base, (uchar) s_addr, *wbuf)) { ! 13465: n_error++; ! 13466: } ! 13467: } ! 13468: *wbuf = sum; ! 13469: if (sum != AscWriteEEPWord(iop_base, (uchar) s_addr, sum)) { ! 13470: n_error++; ! 13471: } ! 13472: wbuf = (ushort *) cfg_buf; ! 13473: for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { ! 13474: if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) { ! 13475: n_error++; ! 13476: } ! 13477: } ! 13478: for (s_addr = cfg_beg; s_addr <= cfg_end; ! 13479: s_addr++, wbuf++) { ! 13480: if (*wbuf != AscReadEEPWord(iop_base, (uchar) s_addr)) { ! 13481: n_error++; ! 13482: } ! 13483: } ! 13484: return (n_error); ! 13485: } ! 13486: ! 13487: ASC_INITFUNC( ! 13488: STATIC int ! 13489: AscSetEEPConfig( ! 13490: PortAddr iop_base, ! 13491: ASCEEP_CONFIG * cfg_buf, ushort bus_type ! 13492: ) ! 13493: ) ! 13494: { ! 13495: int retry; ! 13496: int n_error; ! 13497: ! 13498: retry = 0; ! 13499: while (TRUE) { ! 13500: if ((n_error = AscSetEEPConfigOnce(iop_base, cfg_buf, ! 13501: bus_type)) == 0) { ! 13502: break; ! 13503: } ! 13504: if (++retry > ASC_EEP_MAX_RETRY) { ! 13505: break; ! 13506: } ! 13507: } ! 13508: return (n_error); ! 13509: } ! 13510: ! 13511: STATIC void ! 13512: AscAsyncFix( ! 13513: ASC_DVC_VAR asc_ptr_type *asc_dvc, ! 13514: uchar tid_no, ! 13515: ASC_SCSI_INQUIRY *inq) ! 13516: { ! 13517: uchar dvc_type; ! 13518: ASC_SCSI_BIT_ID_TYPE tid_bits; ! 13519: ! 13520: dvc_type = inq->byte0.peri_dvc_type; ! 13521: tid_bits = ASC_TIX_TO_TARGET_ID(tid_no); ! 13522: ! 13523: if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) { ! 13524: if (!(asc_dvc->init_sdtr & tid_bits)) { ! 13525: if ((dvc_type == SCSI_TYPE_CDROM) && ! 13526: (AscCompareString((uchar *) inq->vendor_id, ! 13527: (uchar *) "HP ", 3) == 0)) { ! 13528: asc_dvc->pci_fix_asyn_xfer_always |= tid_bits; ! 13529: } ! 13530: asc_dvc->pci_fix_asyn_xfer |= tid_bits; ! 13531: if ((dvc_type == SCSI_TYPE_PROC) || ! 13532: (dvc_type == SCSI_TYPE_SCANNER)) { ! 13533: asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; ! 13534: } ! 13535: if ((dvc_type == SCSI_TYPE_SASD) && ! 13536: (AscCompareString((uchar *) inq->vendor_id, ! 13537: (uchar *) "TANDBERG", 8) == 0) && ! 13538: (AscCompareString((uchar *) inq->product_id, ! 13539: (uchar *) " TDC 36", 7) == 0)) { ! 13540: asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; ! 13541: } ! 13542: if ((dvc_type == SCSI_TYPE_SASD) && ! 13543: (AscCompareString((uchar *) inq->vendor_id, ! 13544: (uchar *) "WANGTEK ", 8) == 0)) { ! 13545: asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; ! 13546: } ! 13547: ! 13548: if ((dvc_type == SCSI_TYPE_CDROM) && ! 13549: (AscCompareString((uchar *) inq->vendor_id, ! 13550: (uchar *) "NEC ", 8) == 0) && ! 13551: (AscCompareString((uchar *) inq->product_id, ! 13552: (uchar *) "CD-ROM DRIVE ", 16) == 0)) { ! 13553: asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; ! 13554: } ! 13555: ! 13556: if ((dvc_type == SCSI_TYPE_CDROM) && ! 13557: (AscCompareString((uchar *) inq->vendor_id, ! 13558: (uchar *) "YAMAHA", 6) == 0) && ! 13559: (AscCompareString((uchar *) inq->product_id, ! 13560: (uchar *) "CDR400", 6) == 0)) { ! 13561: asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; ! 13562: } ! 13563: if (asc_dvc->pci_fix_asyn_xfer & tid_bits) { ! 13564: AscSetRunChipSynRegAtID(asc_dvc->iop_base, tid_no, ! 13565: ASYN_SDTR_DATA_FIX_PCI_REV_AB); ! 13566: } ! 13567: } ! 13568: } ! 13569: return; ! 13570: } ! 13571: ! 13572: STATIC int ! 13573: AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq) ! 13574: { ! 13575: if ((inq->add_len >= 32) && ! 13576: (AscCompareString((uchar *) inq->vendor_id, ! 13577: (uchar *) "QUANTUM XP34301", 15) == 0) && ! 13578: (AscCompareString((uchar *) inq->product_rev_level, ! 13579: (uchar *) "1071", 4) == 0)) ! 13580: { ! 13581: return 0; ! 13582: } ! 13583: return 1; ! 13584: } ! 13585: ! 13586: STATIC void ! 13587: AscInquiryHandling(ASC_DVC_VAR asc_ptr_type *asc_dvc, ! 13588: uchar tid_no, ASC_SCSI_INQUIRY *inq) ! 13589: { ! 13590: ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no); ! 13591: ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng; ! 13592: ! 13593: orig_init_sdtr = asc_dvc->init_sdtr; ! 13594: orig_use_tagged_qng = asc_dvc->use_tagged_qng; ! 13595: ! 13596: asc_dvc->init_sdtr &= ~tid_bit; ! 13597: asc_dvc->cfg->can_tagged_qng &= ~tid_bit; ! 13598: asc_dvc->use_tagged_qng &= ~tid_bit; ! 13599: ! 13600: if (inq->byte3.rsp_data_fmt >= 2 || inq->byte2.ansi_apr_ver >= 2) { ! 13601: if ((asc_dvc->cfg->sdtr_enable & tid_bit) && inq->byte7.Sync) { ! 13602: asc_dvc->init_sdtr |= tid_bit; ! 13603: } ! 13604: if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) && inq->byte7.CmdQue) { ! 13605: if (AscTagQueuingSafe(inq)) { ! 13606: asc_dvc->use_tagged_qng |= tid_bit; ! 13607: asc_dvc->cfg->can_tagged_qng |= tid_bit; ! 13608: } ! 13609: } ! 13610: } ! 13611: if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) { ! 13612: AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B, ! 13613: asc_dvc->cfg->disc_enable); ! 13614: AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B, ! 13615: asc_dvc->use_tagged_qng); ! 13616: AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B, ! 13617: asc_dvc->cfg->can_tagged_qng); ! 13618: ! 13619: asc_dvc->max_dvc_qng[tid_no] = ! 13620: asc_dvc->cfg->max_tag_qng[tid_no]; ! 13621: AscWriteLramByte(asc_dvc->iop_base, ! 13622: (ushort) (ASCV_MAX_DVC_QNG_BEG + tid_no), ! 13623: asc_dvc->max_dvc_qng[tid_no]); ! 13624: } ! 13625: if (orig_init_sdtr != asc_dvc->init_sdtr) { ! 13626: AscAsyncFix(asc_dvc, tid_no, inq); ! 13627: } ! 13628: return; ! 13629: } ! 13630: ! 13631: STATIC int ! 13632: AscCompareString( ! 13633: ruchar * str1, ! 13634: ruchar * str2, ! 13635: int len ! 13636: ) ! 13637: { ! 13638: int i; ! 13639: int diff; ! 13640: ! 13641: for (i = 0; i < len; i++) { ! 13642: diff = (int) (str1[i] - str2[i]); ! 13643: if (diff != 0) ! 13644: return (diff); ! 13645: } ! 13646: return (0); ! 13647: } ! 13648: ! 13649: STATIC uchar ! 13650: AscReadLramByte( ! 13651: PortAddr iop_base, ! 13652: ushort addr ! 13653: ) ! 13654: { ! 13655: uchar byte_data; ! 13656: ushort word_data; ! 13657: ! 13658: if (isodd_word(addr)) { ! 13659: AscSetChipLramAddr(iop_base, addr - 1); ! 13660: word_data = AscGetChipLramData(iop_base); ! 13661: byte_data = (uchar) ((word_data >> 8) & 0xFF); ! 13662: } else { ! 13663: AscSetChipLramAddr(iop_base, addr); ! 13664: word_data = AscGetChipLramData(iop_base); ! 13665: byte_data = (uchar) (word_data & 0xFF); ! 13666: } ! 13667: return (byte_data); ! 13668: } ! 13669: ! 13670: STATIC ushort ! 13671: AscReadLramWord( ! 13672: PortAddr iop_base, ! 13673: ushort addr ! 13674: ) ! 13675: { ! 13676: ushort word_data; ! 13677: ! 13678: AscSetChipLramAddr(iop_base, addr); ! 13679: word_data = AscGetChipLramData(iop_base); ! 13680: return (word_data); ! 13681: } ! 13682: ! 13683: STATIC ulong ! 13684: AscReadLramDWord( ! 13685: PortAddr iop_base, ! 13686: ushort addr ! 13687: ) ! 13688: { ! 13689: ushort val_low, val_high; ! 13690: ulong dword_data; ! 13691: ! 13692: AscSetChipLramAddr(iop_base, addr); ! 13693: val_low = AscGetChipLramData(iop_base); ! 13694: val_high = AscGetChipLramData(iop_base); ! 13695: dword_data = ((ulong) val_high << 16) | (ulong) val_low; ! 13696: return (dword_data); ! 13697: } ! 13698: ! 13699: STATIC void ! 13700: AscWriteLramWord( ! 13701: PortAddr iop_base, ! 13702: ushort addr, ! 13703: ushort word_val ! 13704: ) ! 13705: { ! 13706: AscSetChipLramAddr(iop_base, addr); ! 13707: AscSetChipLramData(iop_base, word_val); ! 13708: return; ! 13709: } ! 13710: ! 13711: STATIC void ! 13712: AscWriteLramDWord( ! 13713: PortAddr iop_base, ! 13714: ushort addr, ! 13715: ulong dword_val ! 13716: ) ! 13717: { ! 13718: ushort word_val; ! 13719: ! 13720: AscSetChipLramAddr(iop_base, addr); ! 13721: word_val = (ushort) dword_val; ! 13722: AscSetChipLramData(iop_base, word_val); ! 13723: word_val = (ushort) (dword_val >> 16); ! 13724: AscSetChipLramData(iop_base, word_val); ! 13725: return; ! 13726: } ! 13727: ! 13728: STATIC void ! 13729: AscWriteLramByte( ! 13730: PortAddr iop_base, ! 13731: ushort addr, ! 13732: uchar byte_val ! 13733: ) ! 13734: { ! 13735: ushort word_data; ! 13736: ! 13737: if (isodd_word(addr)) { ! 13738: addr--; ! 13739: word_data = AscReadLramWord(iop_base, addr); ! 13740: word_data &= 0x00FF; ! 13741: word_data |= (((ushort) byte_val << 8) & 0xFF00); ! 13742: } else { ! 13743: word_data = AscReadLramWord(iop_base, addr); ! 13744: word_data &= 0xFF00; ! 13745: word_data |= ((ushort) byte_val & 0x00FF); ! 13746: } ! 13747: AscWriteLramWord(iop_base, addr, word_data); ! 13748: return; ! 13749: } ! 13750: ! 13751: STATIC void ! 13752: AscMemWordCopyToLram( ! 13753: PortAddr iop_base, ! 13754: ushort s_addr, ! 13755: ushort * s_buffer, ! 13756: int words ! 13757: ) ! 13758: { ! 13759: AscSetChipLramAddr(iop_base, s_addr); ! 13760: DvcOutPortWords(iop_base + IOP_RAM_DATA, s_buffer, words); ! 13761: return; ! 13762: } ! 13763: ! 13764: STATIC void ! 13765: AscMemDWordCopyToLram( ! 13766: PortAddr iop_base, ! 13767: ushort s_addr, ! 13768: ulong * s_buffer, ! 13769: int dwords ! 13770: ) ! 13771: { ! 13772: AscSetChipLramAddr(iop_base, s_addr); ! 13773: DvcOutPortDWords(iop_base + IOP_RAM_DATA, s_buffer, dwords); ! 13774: return; ! 13775: } ! 13776: ! 13777: STATIC void ! 13778: AscMemWordCopyFromLram( ! 13779: PortAddr iop_base, ! 13780: ushort s_addr, ! 13781: ushort * d_buffer, ! 13782: int words ! 13783: ) ! 13784: { ! 13785: AscSetChipLramAddr(iop_base, s_addr); ! 13786: DvcInPortWords(iop_base + IOP_RAM_DATA, d_buffer, words); ! 13787: return; ! 13788: } ! 13789: ! 13790: STATIC ulong ! 13791: AscMemSumLramWord( ! 13792: PortAddr iop_base, ! 13793: ushort s_addr, ! 13794: rint words ! 13795: ) ! 13796: { ! 13797: ulong sum; ! 13798: int i; ! 13799: ! 13800: sum = 0L; ! 13801: for (i = 0; i < words; i++, s_addr += 2) { ! 13802: sum += AscReadLramWord(iop_base, s_addr); ! 13803: } ! 13804: return (sum); ! 13805: } ! 13806: ! 13807: STATIC void ! 13808: AscMemWordSetLram( ! 13809: PortAddr iop_base, ! 13810: ushort s_addr, ! 13811: ushort set_wval, ! 13812: rint words ! 13813: ) ! 13814: { ! 13815: rint i; ! 13816: ! 13817: AscSetChipLramAddr(iop_base, s_addr); ! 13818: for (i = 0; i < words; i++) { ! 13819: AscSetChipLramData(iop_base, set_wval); ! 13820: } ! 13821: return; ! 13822: } ! 13823: ! 13824: ! 13825: /* ! 13826: * --- Adv Library Functions ! 13827: */ ! 13828: ! 13829: /* a_qswap.h */ ! 13830: STATIC unsigned char _adv_mcode_buf[] ASC_INITDATA = { ! 13831: 0x9C, 0xF0, 0x80, 0x01, 0x00, 0xF0, 0x44, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13832: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13833: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x01, 0xD6, 0x11, 0x00, 0x00, 0x70, 0x01, ! 13834: 0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x10, 0x2D, 0x03, 0x00, 0x00, 0x00, 0x00, ! 13835: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13836: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13837: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13838: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13839: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13840: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13841: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13842: 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13843: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13844: 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, ! 13845: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13846: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13847: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13848: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13849: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, ! 13850: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13851: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13852: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13853: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ! 13854: 0x00, 0x00, 0x04, 0xF7, 0x70, 0x01, 0x0C, 0x1C, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF2, 0xD6, 0x0A, ! 13855: 0x04, 0xF7, 0x70, 0x01, 0x06, 0xF7, 0x02, 0x00, 0x3E, 0x57, 0x3C, 0x56, 0x0C, 0x1C, 0x00, 0xFC, ! 13856: 0xA6, 0x00, 0x01, 0x58, 0xAA, 0x13, 0x20, 0xF0, 0xA6, 0x03, 0x06, 0xEC, 0xB9, 0x00, 0x0E, 0x47, ! 13857: 0x03, 0xE6, 0x10, 0x00, 0xCE, 0x45, 0x02, 0x13, 0x3E, 0x57, 0x06, 0xEA, 0xB9, 0x00, 0x47, 0x4B, ! 13858: 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x4E, 0x12, 0x03, 0xF6, 0xC0, 0x00, ! 13859: 0x00, 0xF2, 0x68, 0x0A, 0x41, 0x58, 0x03, 0xF6, 0xD0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x49, 0x44, ! 13860: 0x59, 0xF0, 0x0A, 0x02, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x44, 0x58, 0x00, 0xF2, ! 13861: 0xE2, 0x0D, 0x02, 0xCC, 0x4A, 0xE4, 0x01, 0x00, 0x55, 0xF0, 0x08, 0x03, 0x45, 0xF4, 0x02, 0x00, ! 13862: 0x83, 0x5A, 0x04, 0xCC, 0x01, 0x4A, 0x12, 0x12, 0x00, 0xF2, 0xE2, 0x0D, 0x00, 0xCD, 0x48, 0xE4, ! 13863: 0x01, 0x00, 0xE9, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0xFA, 0x10, 0x0E, 0x47, 0x03, 0xE6, 0x10, 0x00, ! 13864: 0xCE, 0x45, 0x02, 0x13, 0x3E, 0x57, 0xCE, 0x47, 0x97, 0x13, 0x04, 0xEC, 0xB4, 0x00, 0x00, 0xF2, ! 13865: 0xE2, 0x0D, 0x00, 0xCD, 0x48, 0xE4, 0x00, 0x00, 0x12, 0x12, 0x3E, 0x57, 0x06, 0xCC, 0x45, 0xF4, ! 13866: 0x02, 0x00, 0x83, 0x5A, 0x00, 0xCC, 0x00, 0xEA, 0xB4, 0x00, 0x92, 0x10, 0x00, 0xF0, 0x8C, 0x01, ! 13867: 0x43, 0xF0, 0x5C, 0x02, 0x44, 0xF0, 0x60, 0x02, 0x45, 0xF0, 0x64, 0x02, 0x46, 0xF0, 0x68, 0x02, ! 13868: 0x47, 0xF0, 0x6E, 0x02, 0x48, 0xF0, 0x9E, 0x02, 0xB9, 0x54, 0x62, 0x10, 0x00, 0x1C, 0x5A, 0x10, ! 13869: 0x02, 0x1C, 0x56, 0x10, 0x1E, 0x1C, 0x52, 0x10, 0x00, 0xF2, 0x1E, 0x11, 0x50, 0x10, 0x06, 0xFC, ! 13870: 0xA8, 0x00, 0x03, 0xF6, 0xBE, 0x00, 0x00, 0xF2, 0x4E, 0x0A, 0x8C, 0x10, 0x01, 0xF6, 0x01, 0x00, ! 13871: 0x01, 0xFA, 0xA8, 0x00, 0x00, 0xF2, 0x2C, 0x0B, 0x06, 0x10, 0xB9, 0x54, 0x01, 0xFA, 0xA8, 0x00, ! 13872: 0x03, 0xF6, 0xBE, 0x00, 0x00, 0xF2, 0x58, 0x0A, 0x01, 0xFC, 0xA8, 0x00, 0x20, 0x10, 0x58, 0x1C, ! 13873: 0x00, 0xF2, 0x1C, 0x0B, 0x5A, 0x1C, 0x01, 0xF6, 0x01, 0x00, 0x38, 0x54, 0x00, 0xFA, 0xA6, 0x00, ! 13874: 0x01, 0xFA, 0xA8, 0x00, 0x20, 0x1C, 0x00, 0xF0, 0x72, 0x01, 0x01, 0xF6, 0x01, 0x00, 0x38, 0x54, ! 13875: 0x00, 0xFA, 0xA6, 0x00, 0x01, 0xFA, 0xA8, 0x00, 0x20, 0x1C, 0x00, 0xF0, 0x80, 0x01, 0x03, 0xF6, ! 13876: 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x0A, 0x13, 0x00, 0xF2, 0x38, 0x10, 0x00, 0xF2, ! 13877: 0x54, 0x0F, 0x24, 0x10, 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x02, 0xF6, 0xD0, 0x00, ! 13878: 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x49, 0x44, 0x5B, 0xF0, 0x04, 0x03, 0x00, 0xF2, 0x9C, 0x0F, ! 13879: 0x00, 0xF0, 0x80, 0x01, 0x00, 0xF2, 0x14, 0x10, 0x0C, 0x1C, 0x02, 0x4B, 0xBF, 0x57, 0x9E, 0x43, ! 13880: 0x77, 0x57, 0x07, 0x4B, 0x20, 0xF0, 0xA6, 0x03, 0x40, 0x1C, 0x1E, 0xF0, 0x30, 0x03, 0x26, 0xF0, ! 13881: 0x2C, 0x03, 0xA0, 0xF0, 0x1A, 0x03, 0x11, 0xF0, 0xA6, 0x03, 0x12, 0x10, 0x9F, 0xF0, 0x3E, 0x03, ! 13882: 0x46, 0x1C, 0x82, 0xE7, 0x05, 0x00, 0x9E, 0xE7, 0x11, 0x00, 0x00, 0xF0, 0x06, 0x0A, 0x0C, 0x1C, ! 13883: 0x48, 0x1C, 0x46, 0x1C, 0x38, 0x54, 0x00, 0xEC, 0xBA, 0x00, 0x08, 0x44, 0x00, 0xEA, 0xBA, 0x00, ! 13884: 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x08, 0x44, 0x00, 0x4C, 0x82, 0xE7, 0x02, 0x00, ! 13885: 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x70, 0x03, 0x00, 0xF2, 0x60, 0x0B, ! 13886: 0x06, 0xF0, 0x80, 0x03, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A, ! 13887: 0x00, 0xFC, 0xBE, 0x00, 0x98, 0x57, 0x55, 0xF0, 0xAC, 0x04, 0x01, 0xE6, 0x0C, 0x00, 0x00, 0xF2, ! 13888: 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x01, 0xF0, ! 13889: 0x7C, 0x02, 0x00, 0xF0, 0x8A, 0x02, 0x46, 0x1C, 0x0C, 0x1C, 0x67, 0x1B, 0xBF, 0x57, 0x77, 0x57, ! 13890: 0x02, 0x4B, 0x48, 0x1C, 0x32, 0x1C, 0x00, 0xF2, 0x92, 0x0D, 0x30, 0x1C, 0x96, 0xF0, 0xBC, 0x03, ! 13891: 0xB1, 0xF0, 0xC0, 0x03, 0x1E, 0xF0, 0xFC, 0x09, 0x85, 0xF0, 0x02, 0x0A, 0x00, 0xFC, 0xBE, 0x00, ! 13892: 0x98, 0x57, 0x14, 0x12, 0x01, 0xE6, 0x0C, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, ! 13893: 0x01, 0xF0, 0x7C, 0x02, 0x00, 0xF0, 0x8A, 0x02, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, ! 13894: 0x01, 0x48, 0x55, 0xF0, 0x98, 0x04, 0x03, 0x82, 0x03, 0xFC, 0xA0, 0x00, 0x9B, 0x57, 0x40, 0x12, ! 13895: 0x69, 0x18, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x42, 0x04, 0x69, 0x08, 0x00, 0xF2, 0x12, 0x11, ! 13896: 0x85, 0xF0, 0x02, 0x0A, 0x68, 0x08, 0x4C, 0x44, 0x28, 0x12, 0x44, 0x48, 0x03, 0xF6, 0xE0, 0x00, ! 13897: 0x00, 0xF2, 0x68, 0x0A, 0x45, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xCC, 0x01, 0x48, 0x55, 0xF0, ! 13898: 0x98, 0x04, 0x4C, 0x44, 0xEF, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2, 0x14, 0x10, 0x08, 0x10, ! 13899: 0x68, 0x18, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0x04, 0x80, 0x18, 0xE4, 0x10, 0x00, 0x28, 0x12, ! 13900: 0x01, 0xE6, 0x06, 0x00, 0x04, 0x80, 0x18, 0xE4, 0x01, 0x00, 0x04, 0x12, 0x01, 0xE6, 0x0D, 0x00, ! 13901: 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x04, 0xE6, 0x02, 0x00, 0x9E, 0xE7, 0x15, 0x00, ! 13902: 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x69, 0x08, 0x05, 0x80, 0x48, 0xE4, 0x00, 0x00, ! 13903: 0x0C, 0x12, 0x00, 0xE6, 0x11, 0x00, 0x00, 0xEA, 0xB8, 0x00, 0x00, 0xF2, 0xB6, 0x10, 0x82, 0xE7, ! 13904: 0x02, 0x00, 0x1C, 0x90, 0x40, 0x5C, 0x00, 0x16, 0x01, 0xE6, 0x06, 0x00, 0x00, 0xF2, 0x4E, 0x0D, ! 13905: 0x01, 0xF0, 0x80, 0x01, 0x1E, 0xF0, 0x80, 0x01, 0x00, 0xF0, 0xA0, 0x04, 0x42, 0x5B, 0x06, 0xF7, ! 13906: 0x03, 0x00, 0x46, 0x59, 0xBF, 0x57, 0x77, 0x57, 0x01, 0xE6, 0x80, 0x00, 0x07, 0x80, 0x31, 0x44, ! 13907: 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x56, 0x13, 0x20, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x4E, 0x12, ! 13908: 0x00, 0xFC, 0xA2, 0x00, 0x98, 0x57, 0x55, 0xF0, 0x1C, 0x05, 0x31, 0xE4, 0x40, 0x00, 0x00, 0xFC, ! 13909: 0xA0, 0x00, 0x98, 0x57, 0x36, 0x12, 0x4C, 0x1C, 0x00, 0xF2, 0x12, 0x11, 0x89, 0x48, 0x00, 0xF2, ! 13910: 0x12, 0x11, 0x86, 0xF0, 0x2E, 0x05, 0x82, 0xE7, 0x06, 0x00, 0x1B, 0x80, 0x48, 0xE4, 0x22, 0x00, ! 13911: 0x5B, 0xF0, 0x0C, 0x05, 0x48, 0xE4, 0x20, 0x00, 0x59, 0xF0, 0x10, 0x05, 0x00, 0xE6, 0x20, 0x00, ! 13912: 0x09, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0x2E, 0x05, 0x83, 0x80, 0x04, 0x10, 0x00, 0xF2, ! 13913: 0xA2, 0x0D, 0x00, 0xE6, 0x01, 0x00, 0x00, 0xEA, 0x26, 0x01, 0x01, 0xEA, 0x27, 0x01, 0x04, 0x80, ! 13914: 0x18, 0xE4, 0x10, 0x00, 0x36, 0x12, 0xB9, 0x54, 0x00, 0xF2, 0xF6, 0x0E, 0x01, 0xE6, 0x06, 0x00, ! 13915: 0x04, 0x80, 0x18, 0xE4, 0x01, 0x00, 0x04, 0x12, 0x01, 0xE6, 0x0D, 0x00, 0x00, 0xF2, 0x4E, 0x0D, ! 13916: 0x00, 0xF2, 0x12, 0x11, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x04, 0xE6, 0x02, 0x00, ! 13917: 0x9E, 0xE7, 0x15, 0x00, 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0xFC, 0x20, 0x01, ! 13918: 0x98, 0x57, 0x34, 0x12, 0x00, 0xFC, 0x24, 0x01, 0x98, 0x57, 0x2C, 0x13, 0xB9, 0x54, 0x00, 0xF2, ! 13919: 0xF6, 0x0E, 0x86, 0xF0, 0xA8, 0x05, 0x03, 0xF6, 0x01, 0x00, 0x00, 0xF2, 0x8C, 0x0E, 0x85, 0xF0, ! 13920: 0x9E, 0x05, 0x82, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x82, 0xE7, 0x02, 0x00, 0x00, 0xFC, ! 13921: 0x24, 0x01, 0xB0, 0x57, 0x00, 0xFA, 0x24, 0x01, 0x00, 0xFC, 0x9E, 0x00, 0x98, 0x57, 0x5A, 0x12, ! 13922: 0x00, 0xFC, 0xB6, 0x00, 0x98, 0x57, 0x52, 0x13, 0x03, 0xE6, 0x0C, 0x00, 0x00, 0xFC, 0x9C, 0x00, ! 13923: 0x98, 0x57, 0x04, 0x13, 0x03, 0xE6, 0x19, 0x00, 0x05, 0xE6, 0x08, 0x00, 0x00, 0xF6, 0x00, 0x01, ! 13924: 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x18, 0xF4, 0x00, 0x80, 0x04, 0x13, 0x05, 0xE6, ! 13925: 0x0F, 0x00, 0xB9, 0x54, 0x00, 0xF2, 0xF6, 0x0E, 0x86, 0xF0, 0x0A, 0x06, 0x00, 0xF2, 0xBA, 0x0E, ! 13926: 0x85, 0xF0, 0x00, 0x06, 0x82, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x82, 0xE7, 0x02, 0x00, ! 13927: 0x00, 0xFC, 0xB6, 0x00, 0xB0, 0x57, 0x00, 0xFA, 0xB6, 0x00, 0x01, 0xF6, 0x01, 0x00, 0x00, 0xF2, ! 13928: 0xF6, 0x0E, 0x9C, 0x32, 0x4E, 0x1C, 0x32, 0x1C, 0x00, 0xF2, 0x92, 0x0D, 0x30, 0x1C, 0x82, 0xE7, ! 13929: 0x04, 0x00, 0xB1, 0xF0, 0x22, 0x06, 0x0A, 0xF0, 0x3E, 0x06, 0x05, 0xF0, 0xD6, 0x06, 0x06, 0xF0, ! 13930: 0xDC, 0x06, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A, 0x04, 0x80, ! 13931: 0x18, 0xE4, 0x20, 0x00, 0x30, 0x12, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x21, 0x80, ! 13932: 0x18, 0xE4, 0xE0, 0x00, 0x09, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, ! 13933: 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x99, 0xA4, 0x00, 0xF2, 0x12, 0x11, ! 13934: 0x09, 0xE7, 0x00, 0x00, 0x9A, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x02, 0x00, 0x34, 0x12, 0x09, 0xE7, ! 13935: 0x1B, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x21, 0x80, 0x18, 0xE4, 0xE0, 0x00, 0x09, 0x48, 0x00, 0xF2, ! 13936: 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF2, ! 13937: 0x12, 0x11, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x09, 0xE7, 0x00, 0x00, 0x00, 0xF0, ! 13938: 0x0C, 0x09, 0xBB, 0x55, 0x9A, 0x81, 0x03, 0xF7, 0x20, 0x00, 0x09, 0x6F, 0x93, 0x45, 0x55, 0xF0, ! 13939: 0xE2, 0x06, 0xB1, 0xF0, 0xC2, 0x06, 0x0A, 0xF0, 0xBA, 0x06, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, ! 13940: 0xFC, 0x09, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0xF2, 0x60, 0x0B, 0x47, 0x10, 0x09, 0xE7, 0x08, 0x00, ! 13941: 0x41, 0x10, 0x05, 0x80, 0x48, 0xE4, 0x00, 0x00, 0x1E, 0x12, 0x00, 0xE6, 0x11, 0x00, 0x00, 0xEA, ! 13942: 0xB8, 0x00, 0x00, 0xF2, 0xB6, 0x10, 0x2C, 0x90, 0xAE, 0x90, 0x08, 0x50, 0x8A, 0x50, 0x38, 0x54, ! 13943: 0x1F, 0x40, 0x00, 0xF2, 0xB4, 0x0D, 0x08, 0x10, 0x08, 0x90, 0x8A, 0x90, 0x30, 0x50, 0xB2, 0x50, ! 13944: 0x9C, 0x32, 0x0C, 0x92, 0x8E, 0x92, 0x38, 0x54, 0x04, 0x80, 0x30, 0xE4, 0x08, 0x00, 0x04, 0x40, ! 13945: 0x0C, 0x1C, 0x00, 0xF6, 0x03, 0x00, 0xB1, 0xF0, 0x26, 0x07, 0x9E, 0xF0, 0x3A, 0x07, 0x01, 0x48, ! 13946: 0x55, 0xF0, 0xFC, 0x09, 0x0C, 0x1C, 0x10, 0x44, 0xED, 0x10, 0x0B, 0xF0, 0x5E, 0x07, 0x0C, 0xF0, ! 13947: 0x62, 0x07, 0x05, 0xF0, 0x52, 0x07, 0x06, 0xF0, 0x58, 0x07, 0x09, 0xF0, 0x24, 0x09, 0x00, 0xF0, ! 13948: 0x02, 0x0A, 0x00, 0xF2, 0x60, 0x0B, 0xCF, 0x10, 0x09, 0xE7, 0x08, 0x00, 0xC9, 0x10, 0x2E, 0x1C, ! 13949: 0x02, 0x10, 0x2C, 0x1C, 0xAA, 0xF0, 0x64, 0x07, 0xAC, 0xF0, 0x72, 0x07, 0x40, 0x10, 0x34, 0x1C, ! 13950: 0xF3, 0x10, 0xAD, 0xF0, 0x7C, 0x07, 0xC8, 0x10, 0x36, 0x1C, 0xE9, 0x10, 0x2B, 0xF0, 0x82, 0x08, ! 13951: 0x6B, 0x18, 0x18, 0xF4, 0x00, 0xFE, 0x20, 0x12, 0x01, 0x58, 0xD2, 0xF0, 0x82, 0x08, 0x76, 0x18, ! 13952: 0x18, 0xF4, 0x03, 0x00, 0xEC, 0x12, 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0xE2, 0x12, ! 13953: 0x0B, 0xF0, 0x64, 0x07, 0x0C, 0xF0, 0x64, 0x07, 0x36, 0x1C, 0x34, 0x1C, 0xB7, 0x10, 0x38, 0x54, ! 13954: 0xB9, 0x54, 0x84, 0x80, 0x19, 0xE4, 0x20, 0x00, 0xB2, 0x13, 0x85, 0x80, 0x81, 0x48, 0x66, 0x12, ! 13955: 0x04, 0x80, 0x18, 0xE4, 0x08, 0x00, 0x58, 0x13, 0x1F, 0x80, 0x08, 0x44, 0xC8, 0x44, 0x9F, 0x12, ! 13956: 0x1F, 0x40, 0x34, 0x91, 0xB6, 0x91, 0x44, 0x55, 0xE5, 0x55, 0x02, 0xEC, 0xB8, 0x00, 0x02, 0x49, ! 13957: 0xBB, 0x55, 0x82, 0x81, 0xC0, 0x55, 0x48, 0xF4, 0x0F, 0x00, 0x5A, 0xF0, 0x1A, 0x08, 0x4A, 0xE4, ! 13958: 0x17, 0x00, 0xD5, 0xF0, 0xFA, 0x07, 0x02, 0xF6, 0x0F, 0x00, 0x02, 0xF4, 0x02, 0x00, 0x02, 0xEA, ! 13959: 0xB8, 0x00, 0x04, 0x91, 0x86, 0x91, 0x02, 0x4B, 0x2C, 0x90, 0x08, 0x50, 0x2E, 0x90, 0x0A, 0x50, ! 13960: 0x2C, 0x51, 0xAE, 0x51, 0x00, 0xF2, 0xB6, 0x10, 0x38, 0x54, 0x00, 0xF2, 0xB4, 0x0D, 0x56, 0x10, ! 13961: 0x34, 0x91, 0xB6, 0x91, 0x0C, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x08, 0x00, 0x41, 0x12, 0x0C, 0x91, ! 13962: 0x8E, 0x91, 0x04, 0x80, 0x18, 0xE4, 0xF7, 0x00, 0x04, 0x40, 0x30, 0x90, 0xB2, 0x90, 0x36, 0x10, ! 13963: 0x02, 0x80, 0x48, 0xE4, 0x10, 0x00, 0x31, 0x12, 0x82, 0xE7, 0x10, 0x00, 0x84, 0x80, 0x19, 0xE4, ! 13964: 0x20, 0x00, 0x10, 0x13, 0x0C, 0x90, 0x8E, 0x90, 0x5D, 0xF0, 0x78, 0x07, 0x0C, 0x58, 0x8D, 0x58, ! 13965: 0x00, 0xF0, 0x64, 0x07, 0x38, 0x54, 0xB9, 0x54, 0x19, 0x80, 0xF1, 0x10, 0x3A, 0x55, 0x19, 0x81, ! 13966: 0xBB, 0x55, 0x10, 0x90, 0x92, 0x90, 0x10, 0x58, 0x91, 0x58, 0x14, 0x59, 0x95, 0x59, 0x00, 0xF0, ! 13967: 0x64, 0x07, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x06, 0x12, 0x6C, 0x19, 0x19, 0x41, 0x7C, 0x10, ! 13968: 0x6C, 0x19, 0x0C, 0x51, 0xED, 0x19, 0x8E, 0x51, 0x6B, 0x18, 0x18, 0xF4, 0x00, 0xFF, 0x02, 0x13, ! 13969: 0x6A, 0x10, 0x01, 0x58, 0xD2, 0xF0, 0xC0, 0x08, 0x76, 0x18, 0x18, 0xF4, 0x03, 0x00, 0x0A, 0x12, ! 13970: 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0x06, 0x13, 0x9E, 0xE7, 0x16, 0x00, 0x4C, 0x10, ! 13971: 0xD1, 0xF0, 0xCA, 0x08, 0x9E, 0xE7, 0x17, 0x00, 0x42, 0x10, 0xD0, 0xF0, 0xD4, 0x08, 0x9E, 0xE7, ! 13972: 0x19, 0x00, 0x38, 0x10, 0xCF, 0xF0, 0xDE, 0x08, 0x9E, 0xE7, 0x20, 0x00, 0x2E, 0x10, 0xCE, 0xF0, ! 13973: 0xE8, 0x08, 0x9E, 0xE7, 0x21, 0x00, 0x24, 0x10, 0xCD, 0xF0, 0xF2, 0x08, 0x9E, 0xE7, 0x22, 0x00, ! 13974: 0x1A, 0x10, 0xCC, 0xF0, 0x04, 0x09, 0x84, 0x80, 0x19, 0xE4, 0x04, 0x00, 0x06, 0x12, 0x9E, 0xE7, ! 13975: 0x12, 0x00, 0x08, 0x10, 0xCB, 0xF0, 0x0C, 0x09, 0x9E, 0xE7, 0x24, 0x00, 0xB1, 0xF0, 0x0C, 0x09, ! 13976: 0x05, 0xF0, 0x1E, 0x09, 0x09, 0xF0, 0x24, 0x09, 0x1E, 0xF0, 0xFC, 0x09, 0xE4, 0x10, 0x00, 0xF2, ! 13977: 0x60, 0x0B, 0xE9, 0x10, 0x9C, 0x32, 0x82, 0xE7, 0x20, 0x00, 0x32, 0x1C, 0xE9, 0x09, 0x00, 0xF2, ! 13978: 0x12, 0x11, 0x85, 0xF0, 0x02, 0x0A, 0x69, 0x08, 0x01, 0xF0, 0x44, 0x09, 0x1E, 0xF0, 0xFC, 0x09, ! 13979: 0x00, 0xF0, 0x38, 0x09, 0x30, 0x44, 0x06, 0x12, 0x9E, 0xE7, 0x42, 0x00, 0xB8, 0x10, 0x04, 0xF6, ! 13980: 0x01, 0x00, 0xB3, 0x45, 0x74, 0x12, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, 0x22, 0x13, 0x4B, 0xE4, ! 13981: 0x02, 0x00, 0x36, 0x12, 0x4B, 0xE4, 0x28, 0x00, 0xAC, 0x13, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, ! 13982: 0xC8, 0x11, 0x03, 0xF6, 0xD0, 0x00, 0xFA, 0x14, 0x82, 0xE7, 0x01, 0x00, 0x00, 0xF0, 0x80, 0x01, ! 13983: 0x9E, 0xE7, 0x44, 0x00, 0x4B, 0xE4, 0x02, 0x00, 0x06, 0x12, 0x03, 0xE6, 0x02, 0x00, 0x76, 0x10, ! 13984: 0x00, 0xF2, 0xA2, 0x0D, 0x03, 0xE6, 0x02, 0x00, 0x6C, 0x10, 0x00, 0xF2, 0xA2, 0x0D, 0x19, 0x82, ! 13985: 0x34, 0x46, 0x0A, 0x13, 0x03, 0xE6, 0x02, 0x00, 0x9E, 0xE7, 0x43, 0x00, 0x68, 0x10, 0x04, 0x80, ! 13986: 0x30, 0xE4, 0x20, 0x00, 0x04, 0x40, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, 0x82, 0xE7, ! 13987: 0x01, 0x00, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF0, 0x08, 0x03, 0x04, 0x80, 0x18, 0xE4, 0x20, 0x00, ! 13988: 0x06, 0x12, 0x03, 0xE6, 0x02, 0x00, 0x3E, 0x10, 0x04, 0x80, 0x18, 0xE4, 0x02, 0x00, 0x3A, 0x12, ! 13989: 0x04, 0x80, 0x18, 0xE4, 0xFD, 0x00, 0x04, 0x40, 0x1C, 0x1C, 0x9D, 0xF0, 0xEA, 0x09, 0x1C, 0x1C, ! 13990: 0x9D, 0xF0, 0xF0, 0x09, 0xC1, 0x10, 0x9E, 0xE7, 0x13, 0x00, 0x0A, 0x10, 0x9E, 0xE7, 0x41, 0x00, ! 13991: 0x04, 0x10, 0x9E, 0xE7, 0x24, 0x00, 0x00, 0xFC, 0xBE, 0x00, 0x98, 0x57, 0xD5, 0xF0, 0x8A, 0x02, ! 13992: 0x04, 0xE6, 0x04, 0x00, 0x06, 0x10, 0x04, 0xE6, 0x04, 0x00, 0x9D, 0x41, 0x1C, 0x42, 0x9F, 0xE7, ! 13993: 0x00, 0x00, 0x06, 0xF7, 0x02, 0x00, 0x03, 0xF6, 0xE0, 0x00, 0x3C, 0x14, 0x44, 0x58, 0x45, 0x58, ! 13994: 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xF2, 0x7E, 0x10, 0x00, 0xF2, 0xC6, 0x0F, 0x3C, 0x14, 0x1E, 0x1C, ! 13995: 0x00, 0xF0, 0x80, 0x01, 0x12, 0x1C, 0x22, 0x1C, 0xD2, 0x14, 0x00, 0xF0, 0x72, 0x01, 0x83, 0x59, ! 13996: 0x03, 0xDC, 0x73, 0x57, 0x80, 0x5D, 0x00, 0x16, 0x83, 0x59, 0x03, 0xDC, 0x38, 0x54, 0x70, 0x57, ! 13997: 0x33, 0x54, 0x3B, 0x54, 0x80, 0x5D, 0x00, 0x16, 0x03, 0x57, 0x83, 0x59, 0x38, 0x54, 0x00, 0xCC, ! 13998: 0x00, 0x16, 0x03, 0x57, 0x83, 0x59, 0x00, 0x4C, 0x00, 0x16, 0x02, 0x80, 0x48, 0xE4, 0x01, 0x00, ! 13999: 0x0E, 0x12, 0x48, 0xE4, 0x05, 0x00, 0x08, 0x12, 0x00, 0xF2, 0xBC, 0x11, 0x00, 0xF2, 0xC8, 0x11, ! 14000: 0xC1, 0x5A, 0x3A, 0x55, 0x02, 0xEC, 0xB5, 0x00, 0x45, 0x59, 0x00, 0xF2, 0xF6, 0x0D, 0x83, 0x58, ! 14001: 0x30, 0xE7, 0x00, 0x00, 0x10, 0x4D, 0x30, 0xE7, 0x40, 0x00, 0x10, 0x4F, 0x38, 0x90, 0xBA, 0x90, ! 14002: 0x10, 0x5C, 0x80, 0x5C, 0x83, 0x5A, 0x10, 0x4E, 0x04, 0xEA, 0xB5, 0x00, 0x43, 0x5B, 0x03, 0xF4, ! 14003: 0xE0, 0x00, 0x83, 0x59, 0x04, 0xCC, 0x01, 0x4A, 0x0A, 0x12, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, ! 14004: 0x00, 0xF2, 0x38, 0x10, 0x00, 0x16, 0x08, 0x1C, 0x00, 0xFC, 0xAC, 0x00, 0x06, 0x58, 0x67, 0x18, ! 14005: 0x18, 0xF4, 0x8F, 0xE1, 0x01, 0xFC, 0xAE, 0x00, 0x19, 0xF4, 0x70, 0x1E, 0xB0, 0x54, 0x07, 0x58, ! 14006: 0x00, 0xFC, 0xB0, 0x00, 0x08, 0x58, 0x00, 0xFC, 0xB2, 0x00, 0x09, 0x58, 0x0A, 0x1C, 0x00, 0xE6, ! 14007: 0x0F, 0x00, 0x00, 0xEA, 0xB9, 0x00, 0x38, 0x54, 0x00, 0xFA, 0x24, 0x01, 0x00, 0xFA, 0xB6, 0x00, ! 14008: 0x18, 0x1C, 0x14, 0x1C, 0x10, 0x1C, 0x32, 0x1C, 0x12, 0x1C, 0x00, 0x16, 0x3E, 0x57, 0x0C, 0x14, ! 14009: 0x0E, 0x47, 0x07, 0xE6, 0x10, 0x00, 0xCE, 0x47, 0xF5, 0x13, 0x00, 0x16, 0x00, 0xF2, 0xA2, 0x0D, ! 14010: 0x02, 0x4B, 0x03, 0xF6, 0xE0, 0x00, 0x00, 0xF2, 0x68, 0x0A, 0x01, 0x48, 0x20, 0x12, 0x44, 0x58, ! 14011: 0x45, 0x58, 0x9E, 0xE7, 0x15, 0x00, 0x9C, 0xE7, 0x04, 0x00, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0xF2, ! 14012: 0x7E, 0x10, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2, 0x7A, 0x0A, 0x1E, 0x1C, 0xD5, 0x10, 0x00, 0x16, ! 14013: 0x69, 0x08, 0x48, 0xE4, 0x04, 0x00, 0x64, 0x12, 0x48, 0xE4, 0x02, 0x00, 0x20, 0x12, 0x48, 0xE4, ! 14014: 0x03, 0x00, 0x1A, 0x12, 0x48, 0xE4, 0x08, 0x00, 0x14, 0x12, 0x48, 0xE4, 0x01, 0x00, 0xF0, 0x12, ! 14015: 0x48, 0xE4, 0x07, 0x00, 0x12, 0x12, 0x01, 0xE6, 0x07, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, ! 14016: 0x12, 0x11, 0x05, 0xF0, 0x60, 0x0B, 0x00, 0x16, 0x00, 0xE6, 0x01, 0x00, 0x00, 0xEA, 0x99, 0x00, ! 14017: 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0xE7, 0x12, 0x48, 0xE4, 0x06, 0x00, 0xE1, 0x12, 0x01, 0xE6, ! 14018: 0x06, 0x00, 0x00, 0xF2, 0x4E, 0x0D, 0x00, 0xF2, 0x12, 0x11, 0x04, 0xE6, 0x02, 0x00, 0x9E, 0xE7, ! 14019: 0x15, 0x00, 0x01, 0xF0, 0x1C, 0x0A, 0x00, 0xF0, 0x02, 0x0A, 0x00, 0x16, 0x02, 0x80, 0x48, 0xE4, ! 14020: 0x10, 0x00, 0x1C, 0x12, 0x82, 0xE7, 0x08, 0x00, 0x3C, 0x56, 0x03, 0x82, 0x00, 0xF2, 0xE2, 0x0D, ! 14021: 0x30, 0xE7, 0x08, 0x00, 0x04, 0xF7, 0x70, 0x01, 0x06, 0xF7, 0x02, 0x00, 0x00, 0xF0, 0x80, 0x01, ! 14022: 0x6C, 0x19, 0xED, 0x19, 0x5D, 0xF0, 0xD4, 0x0B, 0x44, 0x55, 0xE5, 0x55, 0x59, 0xF0, 0x52, 0x0C, ! 14023: 0x04, 0x55, 0xA5, 0x55, 0x1F, 0x80, 0x01, 0xEC, 0xB8, 0x00, 0x82, 0x48, 0x82, 0x80, 0x49, 0x44, ! 14024: 0x2E, 0x13, 0x01, 0xEC, 0xB8, 0x00, 0x41, 0xE4, 0x02, 0x00, 0x01, 0xEA, 0xB8, 0x00, 0x49, 0xE4, ! 14025: 0x11, 0x00, 0x59, 0xF0, 0x2E, 0x0C, 0x01, 0xE6, 0x17, 0x00, 0x01, 0xEA, 0xB8, 0x00, 0x02, 0x4B, ! 14026: 0x88, 0x90, 0xAC, 0x50, 0x8A, 0x90, 0xAE, 0x50, 0x01, 0xEC, 0xB8, 0x00, 0x82, 0x48, 0x82, 0x80, ! 14027: 0x10, 0x44, 0x02, 0x4B, 0x1F, 0x40, 0xC0, 0x44, 0x00, 0xF2, 0xB4, 0x0D, 0x04, 0x55, 0xA5, 0x55, ! 14028: 0x9F, 0x10, 0x0C, 0x51, 0x8E, 0x51, 0x30, 0x90, 0xB2, 0x90, 0x00, 0x56, 0xA1, 0x56, 0x30, 0x50, ! 14029: 0xB2, 0x50, 0x34, 0x90, 0xB6, 0x90, 0x40, 0x56, 0xE1, 0x56, 0x34, 0x50, 0xB6, 0x50, 0x65, 0x10, ! 14030: 0xB1, 0xF0, 0x70, 0x0C, 0x85, 0xF0, 0xCA, 0x0B, 0xE9, 0x09, 0x4B, 0xE4, 0x03, 0x00, 0x78, 0x12, ! 14031: 0x4B, 0xE4, 0x02, 0x00, 0x01, 0x13, 0xB1, 0xF0, 0x86, 0x0C, 0x85, 0xF0, 0xCA, 0x0B, 0x69, 0x08, ! 14032: 0x48, 0xE4, 0x03, 0x00, 0xD5, 0xF0, 0x86, 0x0B, 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0xCA, 0x0B, ! 14033: 0xE8, 0x09, 0x3C, 0x56, 0x00, 0xFC, 0x20, 0x01, 0x98, 0x57, 0x02, 0x13, 0xBB, 0x45, 0x4B, 0xE4, ! 14034: 0x00, 0x00, 0x08, 0x12, 0x03, 0xE6, 0x01, 0x00, 0x04, 0xF6, 0x00, 0x80, 0xA8, 0x14, 0xD2, 0x14, ! 14035: 0x30, 0x1C, 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x10, 0x13, 0x00, 0xFC, 0xB6, 0x00, 0x98, 0x57, ! 14036: 0x02, 0x13, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF0, 0x8E, 0x0B, 0x00, 0xFC, 0x24, 0x01, 0xB0, 0x57, ! 14037: 0x00, 0xFA, 0x24, 0x01, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0x8E, 0x0B, ! 14038: 0x00, 0xF2, 0x8C, 0x0E, 0x00, 0xF0, 0x8E, 0x0B, 0xB1, 0xF0, 0xF8, 0x0C, 0x85, 0xF0, 0x86, 0x0B, ! 14039: 0x69, 0x08, 0x48, 0xE4, 0x01, 0x00, 0xD5, 0xF0, 0x86, 0x0B, 0xFC, 0x14, 0x42, 0x58, 0x6C, 0x14, ! 14040: 0x80, 0x14, 0x30, 0x1C, 0x4A, 0xF4, 0x02, 0x00, 0x55, 0xF0, 0x86, 0x0B, 0x4A, 0xF4, 0x01, 0x00, ! 14041: 0x0E, 0x12, 0x02, 0x80, 0x48, 0xE4, 0x03, 0x00, 0x06, 0x13, 0x3E, 0x1C, 0x00, 0xF0, 0x8E, 0x0B, ! 14042: 0x00, 0xFC, 0xB6, 0x00, 0xB0, 0x57, 0x00, 0xFA, 0xB6, 0x00, 0x4C, 0x1C, 0x3E, 0x1C, 0x00, 0xF2, ! 14043: 0x12, 0x11, 0x86, 0xF0, 0x8E, 0x0B, 0x00, 0xF2, 0xBA, 0x0E, 0x00, 0xF0, 0x8E, 0x0B, 0x4C, 0x1C, ! 14044: 0xB1, 0xF0, 0x50, 0x0D, 0x85, 0xF0, 0x5C, 0x0D, 0x69, 0x08, 0xF3, 0x10, 0x86, 0xF0, 0x64, 0x0D, ! 14045: 0x4E, 0x1C, 0x89, 0x48, 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01, 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, ! 14046: 0x00, 0xDC, 0x18, 0xF4, 0xFF, 0x7F, 0x30, 0x56, 0x00, 0x5C, 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01, ! 14047: 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x18, 0xF4, 0x00, 0x80, 0x30, 0x56, 0x00, 0x5C, ! 14048: 0x00, 0x16, 0x00, 0xF6, 0x00, 0x01, 0x00, 0x57, 0x00, 0x57, 0x03, 0x58, 0x00, 0xDC, 0x0B, 0x58, ! 14049: 0x00, 0x16, 0x03, 0xF6, 0x24, 0x01, 0x00, 0xF2, 0x58, 0x0A, 0x03, 0xF6, 0xB6, 0x00, 0x00, 0xF2, ! 14050: 0x58, 0x0A, 0x00, 0x16, 0x02, 0xEC, 0xB8, 0x00, 0x02, 0x49, 0x18, 0xF4, 0xFF, 0x00, 0x00, 0x54, ! 14051: 0x00, 0x54, 0x00, 0x54, 0x00, 0xF4, 0x08, 0x00, 0xE1, 0x18, 0x80, 0x54, 0x03, 0x58, 0x00, 0xDD, ! 14052: 0x01, 0xDD, 0x02, 0xDD, 0x03, 0xDC, 0x02, 0x4B, 0x30, 0x50, 0xB2, 0x50, 0x34, 0x51, 0xB6, 0x51, ! 14053: 0x00, 0x16, 0x45, 0x5A, 0x1D, 0xF4, 0xFF, 0x00, 0x85, 0x56, 0x85, 0x56, 0x85, 0x56, 0x05, 0xF4, ! 14054: 0x02, 0x12, 0x83, 0x5A, 0x00, 0x16, 0x1D, 0xF4, 0xFF, 0x00, 0x85, 0x56, 0x85, 0x56, 0x85, 0x56, ! 14055: 0x05, 0xF4, 0x00, 0x12, 0x83, 0x5A, 0x00, 0x16, 0x38, 0x54, 0xBB, 0x55, 0x3C, 0x56, 0xBD, 0x56, ! 14056: 0x00, 0xF2, 0x12, 0x11, 0x85, 0xF0, 0x82, 0x0E, 0xE9, 0x09, 0xC1, 0x59, 0x00, 0xF2, 0x12, 0x11, ! 14057: 0x85, 0xF0, 0x82, 0x0E, 0xE8, 0x0A, 0x83, 0x55, 0x83, 0x55, 0x4B, 0xF4, 0x90, 0x01, 0x5C, 0xF0, ! 14058: 0x36, 0x0E, 0xBD, 0x56, 0x40, 0x10, 0x4B, 0xF4, 0x30, 0x00, 0x59, 0xF0, 0x48, 0x0E, 0x01, 0xF6, ! 14059: 0x0C, 0x00, 0x00, 0xF6, 0x01, 0x00, 0x2E, 0x10, 0x02, 0xFC, 0x9C, 0x00, 0x9A, 0x57, 0x14, 0x13, ! 14060: 0x4B, 0xF4, 0x64, 0x00, 0x59, 0xF0, 0x64, 0x0E, 0x03, 0xF6, 0x64, 0x00, 0x01, 0xF6, 0x19, 0x00, ! 14061: 0x00, 0xF6, 0x01, 0x00, 0x43, 0xF4, 0x33, 0x00, 0x56, 0xF0, 0x76, 0x0E, 0x04, 0xF4, 0x00, 0x01, ! 14062: 0x43, 0xF4, 0x19, 0x00, 0xF3, 0x10, 0xB4, 0x56, 0xC3, 0x58, 0x02, 0xFC, 0x9E, 0x00, 0x9A, 0x57, ! 14063: 0x08, 0x13, 0x3C, 0x56, 0x00, 0xF6, 0x02, 0x00, 0x00, 0x16, 0x00, 0x16, 0x09, 0xE7, 0x01, 0x00, ! 14064: 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xB8, 0x0E, 0x09, 0xE7, 0x02, 0x00, 0x00, 0xF2, 0x12, 0x11, ! 14065: 0x86, 0xF0, 0xB8, 0x0E, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xB8, 0x0E, ! 14066: 0x4E, 0x1C, 0x89, 0x49, 0x00, 0xF2, 0x12, 0x11, 0x00, 0x16, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2, ! 14067: 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x09, 0xE7, 0x03, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, ! 14068: 0xF2, 0x0E, 0x09, 0xE7, 0x01, 0x00, 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x89, 0x49, ! 14069: 0x00, 0xF2, 0x12, 0x11, 0x86, 0xF0, 0xF2, 0x0E, 0x4E, 0x1C, 0x89, 0x4A, 0x00, 0xF2, 0x12, 0x11, ! 14070: 0x00, 0x16, 0x3C, 0x56, 0x00, 0x16, 0x00, 0xEC, 0x26, 0x01, 0x48, 0xE4, 0x01, 0x00, 0x1E, 0x13, ! 14071: 0x38, 0x44, 0x00, 0xEA, 0x26, 0x01, 0x49, 0xF4, 0x00, 0x00, 0x04, 0x12, 0x4E, 0x1C, 0x02, 0x10, ! 14072: 0x4C, 0x1C, 0x01, 0xEC, 0x27, 0x01, 0x89, 0x48, 0x00, 0xF2, 0x12, 0x11, 0x02, 0x14, 0x00, 0x16, ! 14073: 0x85, 0xF0, 0x52, 0x0F, 0x38, 0x54, 0x00, 0xEA, 0x99, 0x00, 0x00, 0xF2, 0x60, 0x0B, 0x02, 0x80, ! 14074: 0x48, 0xE4, 0x06, 0x00, 0x1C, 0x13, 0x00, 0xEC, 0x99, 0x00, 0x48, 0xE4, 0x01, 0x00, 0x0A, 0x12, ! 14075: 0x04, 0x80, 0x30, 0xE4, 0x01, 0x00, 0x04, 0x40, 0x08, 0x10, 0x04, 0x80, 0x18, 0xE4, 0xFE, 0x00, ! 14076: 0x04, 0x40, 0x00, 0x16, 0x02, 0xF6, 0xE0, 0x00, 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x81, 0x48, ! 14077: 0x22, 0x12, 0x00, 0x4E, 0x83, 0x5A, 0x90, 0x4C, 0x20, 0xE7, 0x00, 0x00, 0xC3, 0x58, 0x1B, 0xF4, ! 14078: 0xFF, 0x00, 0x83, 0x55, 0x83, 0x55, 0x83, 0x55, 0x03, 0xF4, 0x00, 0x12, 0x8B, 0x55, 0x83, 0x59, ! 14079: 0x00, 0x4E, 0x00, 0x16, 0x00, 0x4E, 0x02, 0xF6, 0xF0, 0x00, 0x02, 0x57, 0x03, 0x59, 0x00, 0x4E, ! 14080: 0x83, 0x5A, 0x30, 0xE7, 0x00, 0x00, 0x20, 0xE7, 0x00, 0x00, 0x00, 0x16, 0x02, 0xF6, 0xF0, 0x00, ! 14081: 0x02, 0x57, 0x03, 0x59, 0x01, 0xCC, 0x00, 0x4E, 0x83, 0x5A, 0x30, 0xE7, 0x00, 0x00, 0x80, 0x4C, ! 14082: 0xC3, 0x58, 0x1B, 0xF4, 0xFF, 0x00, 0x83, 0x55, 0x83, 0x55, 0x83, 0x55, 0x03, 0xF4, 0x00, 0x12, ! 14083: 0x83, 0x59, 0x00, 0x4E, 0x00, 0x16, 0x03, 0xF6, 0xE0, 0x00, 0x03, 0x57, 0x83, 0x59, 0x3A, 0x55, ! 14084: 0x02, 0xCC, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0xC0, 0x5A, 0x40, 0x5C, 0x38, 0x54, 0x00, 0xCD, ! 14085: 0x01, 0xCC, 0x4A, 0x46, 0x0A, 0x13, 0x83, 0x59, 0x00, 0x4C, 0x01, 0x48, 0x16, 0x13, 0x0C, 0x10, ! 14086: 0xC5, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x00, 0x4C, 0x01, 0x48, 0x08, 0x13, 0x05, 0xF6, 0xF0, 0x00, ! 14087: 0x05, 0x57, 0x08, 0x10, 0x45, 0x58, 0x00, 0xF2, 0xF6, 0x0D, 0x8D, 0x56, 0x83, 0x5A, 0x80, 0x4C, ! 14088: 0x05, 0x17, 0x00, 0x16, 0x02, 0x4B, 0x06, 0xF7, 0x04, 0x00, 0x62, 0x0B, 0x03, 0x82, 0x00, 0xF2, ! 14089: 0xE2, 0x0D, 0x02, 0x80, 0x00, 0x4C, 0x45, 0xF4, 0x02, 0x00, 0x52, 0x14, 0x06, 0xF7, 0x02, 0x00, ! 14090: 0x06, 0x14, 0x00, 0xF2, 0x54, 0x0F, 0x00, 0x16, 0x02, 0x4B, 0x01, 0xF6, 0xFF, 0x00, 0x38, 0x1C, ! 14091: 0x05, 0xF4, 0x04, 0x00, 0x83, 0x5A, 0x18, 0xDF, 0x19, 0xDF, 0x1D, 0xF7, 0x3C, 0x00, 0xB8, 0xF0, ! 14092: 0x4E, 0x10, 0x9C, 0x14, 0x01, 0x48, 0x1C, 0x13, 0x0E, 0xF7, 0x3C, 0x00, 0x03, 0xF7, 0x04, 0x00, ! 14093: 0xAF, 0x19, 0x03, 0x42, 0x45, 0xF4, 0x02, 0x00, 0x83, 0x5A, 0x02, 0xCC, 0x02, 0x41, 0x45, 0xF4, ! 14094: 0x02, 0x00, 0x00, 0x16, 0x91, 0x44, 0xD5, 0xF0, 0x3E, 0x10, 0x00, 0xF0, 0x9E, 0x02, 0x01, 0xF6, ! 14095: 0xFF, 0x00, 0x38, 0x1C, 0x05, 0xF4, 0x04, 0x00, 0x83, 0x5A, 0x18, 0xDF, 0x19, 0xDF, 0x0E, 0xF7, ! 14096: 0x3C, 0x00, 0x03, 0xF7, 0x04, 0x00, 0x0F, 0x79, 0x1C, 0xF7, 0x3C, 0x00, 0xB8, 0xF0, 0x9C, 0x10, ! 14097: 0x4E, 0x14, 0x01, 0x48, 0x06, 0x13, 0x45, 0xF4, 0x04, 0x00, 0x00, 0x16, 0x91, 0x44, 0xD5, 0xF0, ! 14098: 0x82, 0x10, 0x00, 0xF0, 0x9E, 0x02, 0x02, 0xF6, 0xFF, 0x00, 0x38, 0x1C, 0x2C, 0xBC, 0xAE, 0xBC, ! 14099: 0xE2, 0x08, 0x00, 0xEC, 0xB8, 0x00, 0x02, 0x48, 0x1D, 0xF7, 0x80, 0x00, 0xB8, 0xF0, 0xCC, 0x10, ! 14100: 0x1E, 0x14, 0x01, 0x48, 0x0E, 0x13, 0x0E, 0xF7, 0x80, 0x00, 0x38, 0x54, 0x03, 0x58, 0xAF, 0x19, ! 14101: 0x82, 0x48, 0x00, 0x16, 0x82, 0x48, 0x12, 0x45, 0xD5, 0xF0, 0xBA, 0x10, 0x00, 0xF0, 0x9E, 0x02, ! 14102: 0x39, 0xF0, 0xF8, 0x10, 0x38, 0x44, 0x00, 0x16, 0x7E, 0x18, 0x18, 0xF4, 0x03, 0x00, 0x04, 0x13, ! 14103: 0x61, 0x18, 0x00, 0x16, 0x38, 0x1C, 0x00, 0xFC, 0x22, 0x01, 0x18, 0xF4, 0x01, 0x00, 0xF1, 0x12, ! 14104: 0xE3, 0x10, 0x30, 0x44, 0x30, 0x44, 0x30, 0x44, 0xB1, 0xF0, 0x18, 0x11, 0x00, 0x16, 0x3E, 0x57, ! 14105: 0x03, 0xF6, 0xE0, 0x00, 0x03, 0x57, 0x83, 0x59, 0x04, 0xCC, 0x01, 0x4A, 0x6A, 0x12, 0x45, 0x5A, ! 14106: 0x00, 0xF2, 0xF6, 0x0D, 0x02, 0x4B, 0x70, 0x14, 0x34, 0x13, 0x02, 0x80, 0x48, 0xE4, 0x08, 0x00, ! 14107: 0x18, 0x12, 0x9C, 0xE7, 0x02, 0x00, 0x9E, 0xE7, 0x15, 0x00, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2, ! 14108: 0x7A, 0x0A, 0x1E, 0x1C, 0x01, 0xF6, 0x01, 0x00, 0x00, 0x16, 0x30, 0xE4, 0x10, 0x00, 0x04, 0x40, ! 14109: 0x00, 0xF2, 0xE2, 0x0D, 0x20, 0xE7, 0x01, 0x00, 0x01, 0xF6, 0x01, 0x00, 0x00, 0x16, 0x04, 0xDC, ! 14110: 0x01, 0x4A, 0x24, 0x12, 0x45, 0x5A, 0x00, 0xF2, 0xF6, 0x0D, 0x43, 0x5B, 0x06, 0xEC, 0x98, 0x00, ! 14111: 0x00, 0xF2, 0x38, 0x10, 0xC6, 0x59, 0x20, 0x14, 0x0A, 0x13, 0x00, 0xF2, 0xC6, 0x0F, 0x00, 0xF2, ! 14112: 0x14, 0x10, 0xA7, 0x10, 0x83, 0x5A, 0xD7, 0x10, 0x0E, 0x47, 0x07, 0xE6, 0x10, 0x00, 0xCE, 0x47, ! 14113: 0x5A, 0xF0, 0x20, 0x11, 0xB9, 0x54, 0x00, 0x16, 0x14, 0x90, 0x96, 0x90, 0x02, 0xFC, 0xA8, 0x00, ! 14114: 0x03, 0xFC, 0xAA, 0x00, 0x48, 0x55, 0x02, 0x13, 0xC9, 0x55, 0x00, 0x16, 0x00, 0xEC, 0xBA, 0x00, ! 14115: 0x10, 0x44, 0x00, 0xEA, 0xBA, 0x00, 0x00, 0x16, 0x03, 0xF6, 0xC0, 0x00, 0x00, 0xF2, 0x68, 0x0A, ! 14116: 0x10, 0x44, 0x00, 0x4C, 0x00, 0x16 ! 14117: }; ! 14118: ! 14119: unsigned short _adv_mcode_size ASC_INITDATA = ! 14120: sizeof(_adv_mcode_buf); /* 0x11D6 */ ! 14121: unsigned long _adv_mcode_chksum ASC_INITDATA = 0x03494981UL; ! 14122: ! 14123: /* a_init.c */ ! 14124: /* ! 14125: * EEPROM Configuration. ! 14126: * ! 14127: * All drivers should use this structure to set the default EEPROM ! 14128: * configuration. The BIOS now uses this structure when it is built. ! 14129: * Additional structure information can be found in a_condor.h where ! 14130: * the structure is defined. ! 14131: */ ! 14132: STATIC ADVEEP_CONFIG ! 14133: Default_EEPROM_Config ASC_INITDATA = { ! 14134: ADV_EEPROM_BIOS_ENABLE, /* cfg_msw */ ! 14135: 0x0000, /* cfg_lsw */ ! 14136: 0xFFFF, /* disc_enable */ ! 14137: 0xFFFF, /* wdtr_able */ ! 14138: 0xFFFF, /* sdtr_able */ ! 14139: 0xFFFF, /* start_motor */ ! 14140: 0xFFFF, /* tagqng_able */ ! 14141: 0xFFFF, /* bios_scan */ ! 14142: 0, /* scam_tolerant */ ! 14143: 7, /* adapter_scsi_id */ ! 14144: 0, /* bios_boot_delay */ ! 14145: 3, /* scsi_reset_delay */ ! 14146: 0, /* bios_id_lun */ ! 14147: 0, /* termination */ ! 14148: 0, /* reserved1 */ ! 14149: 0xFFEF, /* bios_ctrl */ ! 14150: 0xFFFF, /* ultra_able */ ! 14151: 0, /* reserved2 */ ! 14152: ASC_DEF_MAX_HOST_QNG, /* max_host_qng */ ! 14153: ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ ! 14154: 0, /* dvc_cntl */ ! 14155: 0, /* bug_fix */ ! 14156: 0, /* serial_number_word1 */ ! 14157: 0, /* serial_number_word2 */ ! 14158: 0, /* serial_number_word3 */ ! 14159: 0, /* check_sum */ ! 14160: { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, /* oem_name[16] */ ! 14161: 0, /* dvc_err_code */ ! 14162: 0, /* adv_err_code */ ! 14163: 0, /* adv_err_addr */ ! 14164: 0, /* saved_dvc_err_code */ ! 14165: 0, /* saved_adv_err_code */ ! 14166: 0, /* saved_adv_err_addr */ ! 14167: 0 /* num_of_err */ ! 14168: }; ! 14169: ! 14170: /* ! 14171: * Initialize the ADV_DVC_VAR structure. ! 14172: * ! 14173: * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. ! 14174: * ! 14175: * For a non-fatal error return a warning code. If there are no warnings ! 14176: * then 0 is returned. ! 14177: */ ! 14178: ASC_INITFUNC( ! 14179: int ! 14180: AdvInitGetConfig(ADV_DVC_VAR *asc_dvc) ! 14181: ) ! 14182: { ! 14183: ushort warn_code; ! 14184: AdvPortAddr iop_base; ! 14185: uchar pci_cmd_reg; ! 14186: int status; ! 14187: ! 14188: warn_code = 0; ! 14189: asc_dvc->err_code = 0; ! 14190: iop_base = asc_dvc->iop_base; ! 14191: ! 14192: /* ! 14193: * PCI Command Register ! 14194: */ ! 14195: ! 14196: if (((pci_cmd_reg = DvcAdvReadPCIConfigByte(asc_dvc, ! 14197: AscPCIConfigCommandRegister)) ! 14198: & AscPCICmdRegBits_BusMastering) ! 14199: != AscPCICmdRegBits_BusMastering) ! 14200: { ! 14201: pci_cmd_reg |= AscPCICmdRegBits_BusMastering; ! 14202: ! 14203: DvcAdvWritePCIConfigByte(asc_dvc, ! 14204: AscPCIConfigCommandRegister, pci_cmd_reg); ! 14205: ! 14206: if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister)) ! 14207: & AscPCICmdRegBits_BusMastering) ! 14208: != AscPCICmdRegBits_BusMastering) ! 14209: { ! 14210: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; ! 14211: } ! 14212: } ! 14213: ! 14214: /* ! 14215: * PCI Latency Timer ! 14216: * ! 14217: * If the "latency timer" register is 0x20 or above, then we don't need ! 14218: * to change it. Otherwise, set it to 0x20 (i.e. set it to 0x20 if it ! 14219: * comes up less than 0x20). ! 14220: */ ! 14221: if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) { ! 14222: DvcAdvWritePCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer, 0x20); ! 14223: if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) ! 14224: { ! 14225: warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; ! 14226: } ! 14227: } ! 14228: ! 14229: /* ! 14230: * Save the state of the PCI Configuration Command Register ! 14231: * "Parity Error Response Control" Bit. If the bit is clear (0), ! 14232: * in AdvInitAsc3550Driver() tell the microcode to ignore DMA ! 14233: * parity errors. ! 14234: */ ! 14235: asc_dvc->cfg->control_flag = 0; ! 14236: if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister) ! 14237: & AscPCICmdRegBits_ParErrRespCtrl)) == 0) ! 14238: { ! 14239: asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR; ! 14240: } ! 14241: ! 14242: asc_dvc->cur_host_qng = 0; ! 14243: ! 14244: asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) | ! 14245: ADV_LIB_VERSION_MINOR; ! 14246: asc_dvc->cfg->chip_version = ! 14247: AdvGetChipVersion(iop_base, asc_dvc->bus_type); ! 14248: ! 14249: /* ! 14250: * Reset the chip to start and allow register writes. ! 14251: */ ! 14252: if (AdvFindSignature(iop_base) == 0) ! 14253: { ! 14254: asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; ! 14255: return ADV_ERROR; ! 14256: } ! 14257: else { ! 14258: ! 14259: AdvResetChip(asc_dvc); ! 14260: ! 14261: if ((status = AdvInitFromEEP(asc_dvc)) == ADV_ERROR) ! 14262: { ! 14263: return ADV_ERROR; ! 14264: } ! 14265: warn_code |= status; ! 14266: ! 14267: /* ! 14268: * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus ! 14269: * Resets should be performed. ! 14270: */ ! 14271: if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) ! 14272: { ! 14273: AdvResetSCSIBus(asc_dvc); ! 14274: } ! 14275: } ! 14276: ! 14277: return warn_code; ! 14278: } ! 14279: ! 14280: /* ! 14281: * Initialize the ASC3550. ! 14282: * ! 14283: * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. ! 14284: * ! 14285: * For a non-fatal error return a warning code. If there are no warnings ! 14286: * then 0 is returned. ! 14287: */ ! 14288: ASC_INITFUNC( ! 14289: int ! 14290: AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc) ! 14291: ) ! 14292: { ! 14293: AdvPortAddr iop_base; ! 14294: ushort warn_code; ! 14295: ulong sum; ! 14296: int begin_addr; ! 14297: int end_addr; ! 14298: int code_sum; ! 14299: int word; ! 14300: int rql_addr; /* RISC Queue List address */ ! 14301: int i; ! 14302: ushort scsi_cfg1; ! 14303: uchar biosmem[ASC_MC_BIOSLEN]; /* BIOS RISC Memory 0x40-0x8F. */ ! 14304: ! 14305: /* If there is already an error, don't continue. */ ! 14306: if (asc_dvc->err_code != 0) ! 14307: { ! 14308: return ADV_ERROR; ! 14309: } ! 14310: ! 14311: warn_code = 0; ! 14312: iop_base = asc_dvc->iop_base; ! 14313: ! 14314: /* ! 14315: * Save the RISC memory BIOS region before writing the microcode. ! 14316: * The BIOS may already be loaded and using its RISC LRAM region ! 14317: * so its region must be saved and restored. ! 14318: * ! 14319: * Note: This code makes the assumption, which is currently true, ! 14320: * that a chip reset does not clear RISC LRAM. ! 14321: */ ! 14322: for (i = 0; i < ASC_MC_BIOSLEN; i++) ! 14323: { ! 14324: AdvReadByteLram(iop_base, ASC_MC_BIOSMEM + i, biosmem[i]); ! 14325: } ! 14326: ! 14327: /* ! 14328: * Load the Microcode ! 14329: * ! 14330: * Write the microcode image to RISC memory starting at address 0. ! 14331: */ ! 14332: AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); ! 14333: for (word = 0; word < _adv_mcode_size; word += 2) ! 14334: { ! 14335: AdvWriteWordAutoIncLram(iop_base, ! 14336: *((ushort *) (&_adv_mcode_buf[word]))); ! 14337: } ! 14338: ! 14339: /* ! 14340: * Clear the rest of Condor's Internal RAM (8KB). ! 14341: */ ! 14342: for (; word < ADV_CONDOR_MEMSIZE; word += 2) ! 14343: { ! 14344: AdvWriteWordAutoIncLram(iop_base, 0); ! 14345: } ! 14346: ! 14347: /* ! 14348: * Verify the microcode checksum. ! 14349: */ ! 14350: sum = 0; ! 14351: AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); ! 14352: for (word = 0; word < _adv_mcode_size; word += 2) ! 14353: { ! 14354: sum += AdvReadWordAutoIncLram(iop_base); ! 14355: } ! 14356: ! 14357: if (sum != _adv_mcode_chksum) ! 14358: { ! 14359: asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; ! 14360: return ADV_ERROR; ! 14361: } ! 14362: ! 14363: /* ! 14364: * Restore the RISC memory BIOS region. ! 14365: */ ! 14366: for (i = 0; i < ASC_MC_BIOSLEN; i++) ! 14367: { ! 14368: AdvWriteByteLram(iop_base, ASC_MC_BIOSMEM + i, biosmem[i]); ! 14369: } ! 14370: ! 14371: /* ! 14372: * Calculate and write the microcode code checksum to the microcode ! 14373: * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). ! 14374: */ ! 14375: AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); ! 14376: AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); ! 14377: code_sum = 0; ! 14378: for (word = begin_addr; word < end_addr; word += 2) ! 14379: { ! 14380: code_sum += *((ushort *) (&_adv_mcode_buf[word])); ! 14381: } ! 14382: AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); ! 14383: ! 14384: /* ! 14385: * Read microcode version and date. ! 14386: */ ! 14387: AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, asc_dvc->cfg->mcode_date); ! 14388: AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, asc_dvc->cfg->mcode_version); ! 14389: ! 14390: /* ! 14391: * Initialize microcode operating variables ! 14392: */ ! 14393: AdvWriteWordLram(iop_base, ASC_MC_ADAPTER_SCSI_ID, ! 14394: asc_dvc->chip_scsi_id); ! 14395: ! 14396: /* ! 14397: * If the PCI Configuration Command Register "Parity Error Response ! 14398: * Control" Bit was clear (0), then set the microcode variable ! 14399: * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode ! 14400: * to ignore DMA parity errors. ! 14401: */ ! 14402: if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) ! 14403: { ! 14404: /* ! 14405: * Note: Don't remove the use of a temporary variable in ! 14406: * the following code, otherwise the Microsoft C compiler ! 14407: * will turn the following lines into a no-op. ! 14408: */ ! 14409: AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); ! 14410: word |= CONTROL_FLAG_IGNORE_PERR; ! 14411: AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); ! 14412: } ! 14413: ! 14414: /* ! 14415: * Set default microcode operating variables for WDTR, SDTR, and ! 14416: * command tag queuing based on the EEPROM configuration values. ! 14417: * ! 14418: * These ADV_DVC_VAR fields and the microcode variables will be ! 14419: * changed in AdvInquiryHandling() if it is found a device is ! 14420: * incapable of a particular feature. ! 14421: */ ! 14422: ! 14423: /* ! 14424: * Set the microcode ULTRA target mask from EEPROM value. The ! 14425: * SDTR target mask overrides the ULTRA target mask in the ! 14426: * microcode so it is safe to set this value without determining ! 14427: * whether the device supports SDTR. ! 14428: * ! 14429: * Note: There is no way to know whether a device supports ULTRA ! 14430: * speed without attempting a SDTR ULTRA speed negotiation with ! 14431: * the device. The device will reject the speed if it does not ! 14432: * support it by responding with an SDTR message containing a ! 14433: * slower speed. ! 14434: */ ! 14435: AdvWriteWordLram(iop_base, ASC_MC_ULTRA_ABLE, asc_dvc->ultra_able); ! 14436: AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, asc_dvc->cfg->disc_enable); ! 14437: ! 14438: ! 14439: /* ! 14440: * Set SCSI_CFG0 Microcode Default Value. ! 14441: * ! 14442: * The microcode will set the SCSI_CFG0 register using this value ! 14443: * after it is started below. ! 14444: */ ! 14445: AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, ! 14446: PARITY_EN | SEL_TMO_LONG | OUR_ID_EN | asc_dvc->chip_scsi_id); ! 14447: ! 14448: /* ! 14449: * Determine SCSI_CFG1 Microcode Default Value. ! 14450: * ! 14451: * The microcode will set the SCSI_CFG1 register using this value ! 14452: * after it is started below. ! 14453: */ ! 14454: ! 14455: /* Read current SCSI_CFG1 Register value. */ ! 14456: scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); ! 14457: ! 14458: /* ! 14459: * If all three connectors are in use, return an error. ! 14460: */ ! 14461: if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 || ! 14462: (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) ! 14463: { ! 14464: asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION; ! 14465: return ADV_ERROR; ! 14466: } ! 14467: ! 14468: /* ! 14469: * If the internal narrow cable is reversed all of the SCSI_CTRL ! 14470: * register signals will be set. Check for and return an error if ! 14471: * this condition is found. ! 14472: */ ! 14473: if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) ! 14474: { ! 14475: asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; ! 14476: return ADV_ERROR; ! 14477: } ! 14478: ! 14479: /* ! 14480: * If this is a differential board and a single-ended device ! 14481: * is attached to one of the connectors, return an error. ! 14482: */ ! 14483: if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) ! 14484: { ! 14485: asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE; ! 14486: return ADV_ERROR; ! 14487: } ! 14488: ! 14489: /* ! 14490: * If automatic termination control is enabled, then set the ! 14491: * termination value based on a table listed in a_condor.h. ! 14492: * ! 14493: * If manual termination was specified with an EEPROM setting ! 14494: * then 'termination' was set-up in AdvInitFromEEP() and ! 14495: * is ready to be 'ored' into SCSI_CFG1. ! 14496: */ ! 14497: if (asc_dvc->cfg->termination == 0) ! 14498: { ! 14499: /* ! 14500: * The software always controls termination by setting TERM_CTL_SEL. ! 14501: * If TERM_CTL_SEL were set to 0, the hardware would set termination. ! 14502: */ ! 14503: asc_dvc->cfg->termination |= TERM_CTL_SEL; ! 14504: ! 14505: switch(scsi_cfg1 & CABLE_DETECT) ! 14506: { ! 14507: /* TERM_CTL_H: on, TERM_CTL_L: on */ ! 14508: case 0x3: case 0x7: case 0xB: case 0xD: case 0xE: case 0xF: ! 14509: asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L); ! 14510: break; ! 14511: ! 14512: /* TERM_CTL_H: on, TERM_CTL_L: off */ ! 14513: case 0x1: case 0x5: case 0x9: case 0xA: case 0xC: ! 14514: asc_dvc->cfg->termination |= TERM_CTL_H; ! 14515: break; ! 14516: ! 14517: /* TERM_CTL_H: off, TERM_CTL_L: off */ ! 14518: case 0x2: case 0x6: ! 14519: break; ! 14520: } ! 14521: } ! 14522: ! 14523: /* ! 14524: * Clear any set TERM_CTL_H and TERM_CTL_L bits. ! 14525: */ ! 14526: scsi_cfg1 &= ~TERM_CTL; ! 14527: ! 14528: /* ! 14529: * Invert the TERM_CTL_H and TERM_CTL_L bits and then ! 14530: * set 'scsi_cfg1'. The TERM_POL bit does not need to be ! 14531: * referenced, because the hardware internally inverts ! 14532: * the Termination High and Low bits if TERM_POL is set. ! 14533: */ ! 14534: scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL)); ! 14535: ! 14536: /* ! 14537: * Set SCSI_CFG1 Microcode Default Value ! 14538: * ! 14539: * Set filter value and possibly modified termination control ! 14540: * bits in the Microcode SCSI_CFG1 Register Value. ! 14541: * ! 14542: * The microcode will set the SCSI_CFG1 register using this value ! 14543: * after it is started below. ! 14544: */ ! 14545: AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, ! 14546: FLTR_11_TO_20NS | scsi_cfg1); ! 14547: ! 14548: /* ! 14549: * Set SEL_MASK Microcode Default Value ! 14550: * ! 14551: * The microcode will set the SEL_MASK register using this value ! 14552: * after it is started below. ! 14553: */ ! 14554: AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, ! 14555: ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); ! 14556: ! 14557: /* ! 14558: * Link all the RISC Queue Lists together in a doubly-linked ! 14559: * NULL terminated list. ! 14560: * ! 14561: * Skip the NULL (0) queue which is not used. ! 14562: */ ! 14563: for (i = 1, rql_addr = ASC_MC_RISC_Q_LIST_BASE + ASC_MC_RISC_Q_LIST_SIZE; ! 14564: i < ASC_MC_RISC_Q_TOTAL_CNT; ! 14565: i++, rql_addr += ASC_MC_RISC_Q_LIST_SIZE) ! 14566: { ! 14567: /* ! 14568: * Set the current RISC Queue List's RQL_FWD and RQL_BWD pointers ! 14569: * in a one word write and set the state (RQL_STATE) to free. ! 14570: */ ! 14571: AdvWriteWordLram(iop_base, rql_addr, ((i + 1) + ((i - 1) << 8))); ! 14572: AdvWriteByteLram(iop_base, rql_addr + RQL_STATE, ASC_MC_QS_FREE); ! 14573: } ! 14574: ! 14575: /* ! 14576: * Set the Host and RISC Queue List pointers. ! 14577: * ! 14578: * Both sets of pointers are initialized with the same values: ! 14579: * ASC_MC_RISC_Q_FIRST(0x01) and ASC_MC_RISC_Q_LAST (0xFF). ! 14580: */ ! 14581: AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_READY, ASC_MC_RISC_Q_FIRST); ! 14582: AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, ASC_MC_RISC_Q_LAST); ! 14583: ! 14584: AdvWriteByteLram(iop_base, ASC_MC_RISC_NEXT_READY, ASC_MC_RISC_Q_FIRST); ! 14585: AdvWriteByteLram(iop_base, ASC_MC_RISC_NEXT_DONE, ASC_MC_RISC_Q_LAST); ! 14586: ! 14587: /* ! 14588: * Finally, set up the last RISC Queue List (255) with ! 14589: * a NULL forward pointer. ! 14590: */ ! 14591: AdvWriteWordLram(iop_base, rql_addr, (ASC_MC_NULL_Q + ((i - 1) << 8))); ! 14592: AdvWriteByteLram(iop_base, rql_addr + RQL_STATE, ASC_MC_QS_FREE); ! 14593: ! 14594: AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, ! 14595: (ADV_INTR_ENABLE_HOST_INTR | ADV_INTR_ENABLE_GLOBAL_INTR)); ! 14596: ! 14597: /* ! 14598: * Note: Don't remove the use of a temporary variable in ! 14599: * the following code, otherwise the Microsoft C compiler ! 14600: * will turn the following lines into a no-op. ! 14601: */ ! 14602: AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); ! 14603: AdvWriteWordRegister(iop_base, IOPW_PC, word); ! 14604: ! 14605: /* finally, finally, gentlemen, start your engine */ ! 14606: AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); ! 14607: ! 14608: return warn_code; ! 14609: } ! 14610: ! 14611: /* ! 14612: * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and ! 14613: * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while ! 14614: * all of this is done. ! 14615: * ! 14616: * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. ! 14617: * ! 14618: * For a non-fatal error return a warning code. If there are no warnings ! 14619: * then 0 is returned. ! 14620: * ! 14621: * Note: Chip is stopped on entry. ! 14622: */ ! 14623: ASC_INITFUNC( ! 14624: STATIC int ! 14625: AdvInitFromEEP(ADV_DVC_VAR *asc_dvc) ! 14626: ) ! 14627: { ! 14628: AdvPortAddr iop_base; ! 14629: ushort warn_code; ! 14630: ADVEEP_CONFIG eep_config; ! 14631: int i; ! 14632: ! 14633: iop_base = asc_dvc->iop_base; ! 14634: ! 14635: warn_code = 0; ! 14636: ! 14637: /* ! 14638: * Read the board's EEPROM configuration. ! 14639: * ! 14640: * Set default values if a bad checksum is found. ! 14641: */ ! 14642: if (AdvGetEEPConfig(iop_base, &eep_config) != eep_config.check_sum) ! 14643: { ! 14644: warn_code |= ASC_WARN_EEPROM_CHKSUM; ! 14645: ! 14646: /* ! 14647: * Set EEPROM default values. ! 14648: */ ! 14649: for (i = 0; i < sizeof(ADVEEP_CONFIG); i++) ! 14650: { ! 14651: *((uchar *) &eep_config + i) = ! 14652: *((uchar *) &Default_EEPROM_Config + i); ! 14653: } ! 14654: ! 14655: /* ! 14656: * Assume the 6 byte board serial number that was read ! 14657: * from EEPROM is correct even if the EEPROM checksum ! 14658: * failed. ! 14659: */ ! 14660: eep_config.serial_number_word3 = ! 14661: AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 1); ! 14662: eep_config.serial_number_word2 = ! 14663: AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 2); ! 14664: eep_config.serial_number_word1 = ! 14665: AdvReadEEPWord(iop_base, ASC_EEP_DVC_CFG_END - 3); ! 14666: AdvSetEEPConfig(iop_base, &eep_config); ! 14667: } ! 14668: ! 14669: /* ! 14670: * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the ! 14671: * EEPROM configuration that was read. ! 14672: * ! 14673: * This is the mapping of EEPROM fields to Adv Library fields. ! 14674: */ ! 14675: asc_dvc->wdtr_able = eep_config.wdtr_able; ! 14676: asc_dvc->sdtr_able = eep_config.sdtr_able; ! 14677: asc_dvc->ultra_able = eep_config.ultra_able; ! 14678: asc_dvc->tagqng_able = eep_config.tagqng_able; ! 14679: asc_dvc->cfg->disc_enable = eep_config.disc_enable; ! 14680: asc_dvc->max_host_qng = eep_config.max_host_qng; ! 14681: asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; ! 14682: asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID); ! 14683: asc_dvc->start_motor = eep_config.start_motor; ! 14684: asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; ! 14685: asc_dvc->cfg->bios_boot_wait = eep_config.bios_boot_delay; ! 14686: asc_dvc->bios_ctrl = eep_config.bios_ctrl; ! 14687: asc_dvc->no_scam = eep_config.scam_tolerant; ! 14688: asc_dvc->cfg->serial1 = eep_config.serial_number_word1; ! 14689: asc_dvc->cfg->serial2 = eep_config.serial_number_word2; ! 14690: asc_dvc->cfg->serial3 = eep_config.serial_number_word3; ! 14691: ! 14692: /* ! 14693: * Set the host maximum queuing (max. 253, min. 16) and the per device ! 14694: * maximum queuing (max. 63, min. 4). ! 14695: */ ! 14696: if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) ! 14697: { ! 14698: eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; ! 14699: } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) ! 14700: { ! 14701: /* If the value is zero, assume it is uninitialized. */ ! 14702: if (eep_config.max_host_qng == 0) ! 14703: { ! 14704: eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; ! 14705: } else ! 14706: { ! 14707: eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; ! 14708: } ! 14709: } ! 14710: ! 14711: if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) ! 14712: { ! 14713: eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; ! 14714: } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) ! 14715: { ! 14716: /* If the value is zero, assume it is uninitialized. */ ! 14717: if (eep_config.max_dvc_qng == 0) ! 14718: { ! 14719: eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; ! 14720: } else ! 14721: { ! 14722: eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; ! 14723: } ! 14724: } ! 14725: ! 14726: /* ! 14727: * If 'max_dvc_qng' is greater than 'max_host_qng', then ! 14728: * set 'max_dvc_qng' to 'max_host_qng'. ! 14729: */ ! 14730: if (eep_config.max_dvc_qng > eep_config.max_host_qng) ! 14731: { ! 14732: eep_config.max_dvc_qng = eep_config.max_host_qng; ! 14733: } ! 14734: ! 14735: /* ! 14736: * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_CFG 'max_dvc_qng' ! 14737: * values based on possibly adjusted EEPROM values. ! 14738: */ ! 14739: asc_dvc->max_host_qng = eep_config.max_host_qng; ! 14740: asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; ! 14741: ! 14742: ! 14743: /* ! 14744: * If the EEPROM 'termination' field is set to automatic (0), then set ! 14745: * the ADV_DVC_CFG 'termination' field to automatic also. ! 14746: * ! 14747: * If the termination is specified with a non-zero 'termination' ! 14748: * value check that a legal value is set and set the ADV_DVC_CFG ! 14749: * 'termination' field appropriately. ! 14750: */ ! 14751: if (eep_config.termination == 0) ! 14752: { ! 14753: asc_dvc->cfg->termination = 0; /* auto termination */ ! 14754: } else ! 14755: { ! 14756: /* Enable manual control with low off / high off. */ ! 14757: if (eep_config.termination == 1) ! 14758: { ! 14759: asc_dvc->cfg->termination = TERM_CTL_SEL; ! 14760: ! 14761: /* Enable manual control with low off / high on. */ ! 14762: } else if (eep_config.termination == 2) ! 14763: { ! 14764: asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H; ! 14765: ! 14766: /* Enable manual control with low on / high on. */ ! 14767: } else if (eep_config.termination == 3) ! 14768: { ! 14769: asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L; ! 14770: } else ! 14771: { ! 14772: /* ! 14773: * The EEPROM 'termination' field contains a bad value. Use ! 14774: * automatic termination instead. ! 14775: */ ! 14776: asc_dvc->cfg->termination = 0; ! 14777: warn_code |= ASC_WARN_EEPROM_TERMINATION; ! 14778: } ! 14779: } ! 14780: ! 14781: return warn_code; ! 14782: } ! 14783: ! 14784: /* ! 14785: * Read EEPROM configuration into the specified buffer. ! 14786: * ! 14787: * Return a checksum based on the EEPROM configuration read. ! 14788: */ ! 14789: ASC_INITFUNC( ! 14790: STATIC ushort ! 14791: AdvGetEEPConfig(AdvPortAddr iop_base, ADVEEP_CONFIG *cfg_buf) ! 14792: ) ! 14793: { ! 14794: ushort wval, chksum; ! 14795: ushort *wbuf; ! 14796: int eep_addr; ! 14797: ! 14798: wbuf = (ushort *) cfg_buf; ! 14799: chksum = 0; ! 14800: ! 14801: for (eep_addr = ASC_EEP_DVC_CFG_BEGIN; ! 14802: eep_addr < ASC_EEP_DVC_CFG_END; ! 14803: eep_addr++, wbuf++) ! 14804: { ! 14805: wval = AdvReadEEPWord(iop_base, eep_addr); ! 14806: chksum += wval; ! 14807: *wbuf = wval; ! 14808: } ! 14809: *wbuf = AdvReadEEPWord(iop_base, eep_addr); ! 14810: wbuf++; ! 14811: for (eep_addr = ASC_EEP_DVC_CTL_BEGIN; ! 14812: eep_addr < ASC_EEP_MAX_WORD_ADDR; ! 14813: eep_addr++, wbuf++) ! 14814: { ! 14815: *wbuf = AdvReadEEPWord(iop_base, eep_addr); ! 14816: } ! 14817: return chksum; ! 14818: } ! 14819: ! 14820: /* ! 14821: * Read the EEPROM from specified location ! 14822: */ ! 14823: ASC_INITFUNC( ! 14824: STATIC ushort ! 14825: AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr) ! 14826: ) ! 14827: { ! 14828: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ! 14829: ASC_EEP_CMD_READ | eep_word_addr); ! 14830: AdvWaitEEPCmd(iop_base); ! 14831: return AdvReadWordRegister(iop_base, IOPW_EE_DATA); ! 14832: } ! 14833: ! 14834: /* ! 14835: * Wait for EEPROM command to complete ! 14836: */ ! 14837: ASC_INITFUNC( ! 14838: STATIC void ! 14839: AdvWaitEEPCmd(AdvPortAddr iop_base) ! 14840: ) ! 14841: { ! 14842: int eep_delay_ms; ! 14843: ! 14844: for (eep_delay_ms = 0; eep_delay_ms < ASC_EEP_DELAY_MS; eep_delay_ms++) ! 14845: { ! 14846: if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) ! 14847: { ! 14848: break; ! 14849: } ! 14850: DvcSleepMilliSecond(1); ! 14851: } ! 14852: if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == 0) ! 14853: { ! 14854: ADV_ASSERT(0); ! 14855: } ! 14856: return; ! 14857: } ! 14858: ! 14859: /* ! 14860: * Write the EEPROM from 'cfg_buf'. ! 14861: */ ! 14862: ASC_INITFUNC( ! 14863: STATIC void ! 14864: AdvSetEEPConfig(AdvPortAddr iop_base, ADVEEP_CONFIG *cfg_buf) ! 14865: ) ! 14866: { ! 14867: ushort *wbuf; ! 14868: ushort addr, chksum; ! 14869: ! 14870: wbuf = (ushort *) cfg_buf; ! 14871: chksum = 0; ! 14872: ! 14873: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); ! 14874: AdvWaitEEPCmd(iop_base); ! 14875: ! 14876: /* ! 14877: * Write EEPROM from word 0 to word 15 ! 14878: */ ! 14879: for (addr = ASC_EEP_DVC_CFG_BEGIN; ! 14880: addr < ASC_EEP_DVC_CFG_END; addr++, wbuf++) ! 14881: { ! 14882: chksum += *wbuf; ! 14883: AdvWriteWordRegister(iop_base, IOPW_EE_DATA, *wbuf); ! 14884: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); ! 14885: AdvWaitEEPCmd(iop_base); ! 14886: DvcSleepMilliSecond(ASC_EEP_DELAY_MS); ! 14887: } ! 14888: ! 14889: /* ! 14890: * Write EEPROM checksum at word 18 ! 14891: */ ! 14892: AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); ! 14893: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); ! 14894: AdvWaitEEPCmd(iop_base); ! 14895: wbuf++; /* skip over check_sum */ ! 14896: ! 14897: /* ! 14898: * Write EEPROM OEM name at words 19 to 26 ! 14899: */ ! 14900: for (addr = ASC_EEP_DVC_CTL_BEGIN; ! 14901: addr < ASC_EEP_MAX_WORD_ADDR; addr++, wbuf++) ! 14902: { ! 14903: AdvWriteWordRegister(iop_base, IOPW_EE_DATA, *wbuf); ! 14904: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); ! 14905: AdvWaitEEPCmd(iop_base); ! 14906: } ! 14907: AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); ! 14908: AdvWaitEEPCmd(iop_base); ! 14909: return; ! 14910: } ! 14911: ! 14912: /* ! 14913: * This function resets the chip and SCSI bus ! 14914: * ! 14915: * It is up to the caller to add a delay to let the bus settle after ! 14916: * calling this function. ! 14917: * ! 14918: * The SCSI_CFG0, SCSI_CFG1, and MEM_CFG registers are set-up in ! 14919: * AdvInitAsc3550Driver(). Here when doing a write to one of these ! 14920: * registers read first and then write. ! 14921: * ! 14922: * Note: A SCSI Bus Reset can not be done until after the EEPROM ! 14923: * configuration is read to determine whether SCSI Bus Resets ! 14924: * should be performed. ! 14925: */ ! 14926: ASC_INITFUNC( ! 14927: STATIC void ! 14928: AdvResetChip(ADV_DVC_VAR *asc_dvc) ! 14929: ) ! 14930: { ! 14931: AdvPortAddr iop_base; ! 14932: ushort word; ! 14933: uchar byte; ! 14934: ! 14935: iop_base = asc_dvc->iop_base; ! 14936: ! 14937: /* ! 14938: * Reset Chip. ! 14939: */ ! 14940: AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET); ! 14941: DvcSleepMilliSecond(100); ! 14942: AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_WR_IO_REG); ! 14943: ! 14944: /* ! 14945: * Initialize Chip registers. ! 14946: * ! 14947: * Note: Don't remove the use of a temporary variable in the following ! 14948: * code, otherwise the Microsoft C compiler will turn the following lines ! 14949: * into a no-op. ! 14950: */ ! 14951: byte = AdvReadByteRegister(iop_base, IOPB_MEM_CFG); ! 14952: byte |= RAM_SZ_8KB; ! 14953: AdvWriteByteRegister(iop_base, IOPB_MEM_CFG, byte); ! 14954: ! 14955: word = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); ! 14956: word &= ~BIG_ENDIAN; ! 14957: AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, word); ! 14958: ! 14959: /* ! 14960: * Setting the START_CTL_EMFU 3:2 bits sets a FIFO threshold ! 14961: * of 128 bytes. This register is only accessible to the host. ! 14962: */ ! 14963: AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, ! 14964: START_CTL_EMFU | READ_CMD_MRM); ! 14965: } ! 14966: ! 14967: /* a_advlib.c */ ! 14968: /* ! 14969: * Description: ! 14970: * Send a SCSI request to the ASC3550 chip ! 14971: * ! 14972: * If there is no SG list for the request, set 'sg_entry_cnt' to 0. ! 14973: * ! 14974: * If 'sg_real_addr' is non-zero on entry, AscGetSGList() will not be ! 14975: * called. It is assumed the caller has already initialized 'sg_real_addr'. ! 14976: * ! 14977: * Return: ! 14978: * ADV_SUCCESS(1) - the request is in the mailbox ! 14979: * ADV_BUSY(0) - total request count > 253, try later ! 14980: * ADV_ERROR(-1) - invalid scsi request Q ! 14981: */ ! 14982: STATIC int ! 14983: AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ! 14984: ADV_SCSI_REQ_Q *scsiq) ! 14985: { ! 14986: if (scsiq == (ADV_SCSI_REQ_Q *) 0L) ! 14987: { ! 14988: /* 'scsiq' should never be NULL. */ ! 14989: ADV_ASSERT(0); ! 14990: return ADV_ERROR; ! 14991: } ! 14992: ! 14993: return AdvSendScsiCmd(asc_dvc, scsiq); ! 14994: } ! 14995: ! 14996: /* ! 14997: * Reset SCSI Bus and purge all outstanding requests. ! 14998: * ! 14999: * Return Value: ! 15000: * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset. ! 15001: * ! 15002: * Note: Should always return ADV_TRUE. ! 15003: */ ! 15004: STATIC int ! 15005: AdvResetSB(ADV_DVC_VAR *asc_dvc) ! 15006: { ! 15007: int status; ! 15008: ! 15009: status = AdvSendIdleCmd(asc_dvc, (ushort) IDLE_CMD_SCSI_RESET, 0L, 0); ! 15010: ! 15011: AdvResetSCSIBus(asc_dvc); ! 15012: ! 15013: return status; ! 15014: } ! 15015: ! 15016: /* ! 15017: * Reset SCSI Bus and delay. ! 15018: */ ! 15019: STATIC void ! 15020: AdvResetSCSIBus(ADV_DVC_VAR *asc_dvc) ! 15021: { ! 15022: AdvPortAddr iop_base; ! 15023: ushort scsi_ctrl; ! 15024: ! 15025: iop_base = asc_dvc->iop_base; ! 15026: ! 15027: /* ! 15028: * The microcode currently sets the SCSI Bus Reset signal while ! 15029: * handling the AscSendIdleCmd() IDLE_CMD_SCSI_RESET command above. ! 15030: * But the SCSI Bus Reset Hold Time in the microcode is not deterministic ! 15031: * (it may in fact be for less than the SCSI Spec. minimum of 25 us). ! 15032: * Therefore on return the Adv Library sets the SCSI Bus Reset signal ! 15033: * for ASC_SCSI_RESET_HOLD_TIME_US, which is defined to be greater ! 15034: * than 25 us. ! 15035: */ ! 15036: scsi_ctrl = AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL); ! 15037: AdvWriteWordRegister(iop_base, IOPW_SCSI_CTRL, ! 15038: scsi_ctrl | ADV_SCSI_CTRL_RSTOUT); ! 15039: DvcDelayMicroSecond(asc_dvc, (ushort) ASC_SCSI_RESET_HOLD_TIME_US); ! 15040: AdvWriteWordRegister(iop_base, IOPW_SCSI_CTRL, ! 15041: scsi_ctrl & ~ADV_SCSI_CTRL_RSTOUT); ! 15042: ! 15043: DvcSleepMilliSecond((ulong) asc_dvc->scsi_reset_wait * 1000); ! 15044: } ! 15045: ! 15046: ! 15047: /* ! 15048: * Adv Library Interrupt Service Routine ! 15049: * ! 15050: * This function is called by a driver's interrupt service routine. ! 15051: * The function disables and re-enables interrupts. ! 15052: * ! 15053: * When a microcode idle command is completed, the ADV_DVC_VAR ! 15054: * 'idle_cmd_done' field is set to ADV_TRUE. ! 15055: * ! 15056: * Note: AdvISR() can be called when interrupts are disabled or even ! 15057: * when there is no hardware interrupt condition present. It will ! 15058: * always check for completed idle commands and microcode requests. ! 15059: * This is an important feature that shouldn't be changed because it ! 15060: * allows commands to be completed from polling mode loops. ! 15061: * ! 15062: * Return: ! 15063: * ADV_TRUE(1) - interrupt was pending ! 15064: * ADV_FALSE(0) - no interrupt was pending ! 15065: */ ! 15066: STATIC int ! 15067: AdvISR(ADV_DVC_VAR *asc_dvc) ! 15068: { ! 15069: AdvPortAddr iop_base; ! 15070: uchar int_stat; ! 15071: ushort next_done_loc, target_bit; ! 15072: int completed_q; ! 15073: int flags; ! 15074: ADV_SCSI_REQ_Q *scsiq; ! 15075: ASC_REQ_SENSE *sense_data; ! 15076: int ret; ! 15077: ! 15078: flags = DvcEnterCritical(); ! 15079: iop_base = asc_dvc->iop_base; ! 15080: ! 15081: if (AdvIsIntPending(iop_base)) ! 15082: { ! 15083: ret = ADV_TRUE; ! 15084: } else ! 15085: { ! 15086: ret = ADV_FALSE; ! 15087: } ! 15088: ! 15089: /* Reading the register clears the interrupt. */ ! 15090: int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG); ! 15091: ! 15092: if (int_stat & ADV_INTR_STATUS_INTRB) ! 15093: { ! 15094: asc_dvc->idle_cmd_done = ADV_TRUE; ! 15095: } ! 15096: ! 15097: /* ! 15098: * Notify the driver of a hardware detected SCSI Bus Reset. ! 15099: */ ! 15100: if (int_stat & ADV_INTR_STATUS_INTRC) ! 15101: { ! 15102: if (asc_dvc->sbreset_callback != 0) ! 15103: { ! 15104: (*(ADV_SBRESET_CALLBACK) asc_dvc->sbreset_callback)(asc_dvc); ! 15105: } ! 15106: } ! 15107: ! 15108: /* ! 15109: * ASC_MC_HOST_NEXT_DONE (0x129) is actually the last completed RISC ! 15110: * Queue List request. Its forward pointer (RQL_FWD) points to the ! 15111: * current completed RISC Queue List request. ! 15112: */ ! 15113: AdvReadByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, next_done_loc); ! 15114: next_done_loc = ASC_MC_RISC_Q_LIST_BASE + ! 15115: (next_done_loc * ASC_MC_RISC_Q_LIST_SIZE) + RQL_FWD; ! 15116: ! 15117: AdvReadByteLram(iop_base, next_done_loc, completed_q); ! 15118: ! 15119: /* Loop until all completed Q's are processed. */ ! 15120: while (completed_q != ASC_MC_NULL_Q) ! 15121: { ! 15122: AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_DONE, completed_q); ! 15123: ! 15124: next_done_loc = ASC_MC_RISC_Q_LIST_BASE + ! 15125: (completed_q * ASC_MC_RISC_Q_LIST_SIZE); ! 15126: ! 15127: /* ! 15128: * Read the ADV_SCSI_REQ_Q virtual address pointer from ! 15129: * the RISC list entry. The microcode has changed the ! 15130: * ADV_SCSI_REQ_Q physical address to its virtual address. ! 15131: * ! 15132: * Refer to comments at the end of AdvSendScsiCmd() for ! 15133: * more information on the RISC list structure. ! 15134: */ ! 15135: { ! 15136: ushort lsw, msw; ! 15137: AdvReadWordLram(iop_base, next_done_loc + RQL_PHYADDR, lsw); ! 15138: AdvReadWordLram(iop_base, next_done_loc + RQL_PHYADDR + 2, msw); ! 15139: ! 15140: scsiq = (ADV_SCSI_REQ_Q *) (((ulong) msw << 16) | lsw); ! 15141: } ! 15142: ADV_ASSERT(scsiq != NULL); ! 15143: ! 15144: target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id); ! 15145: ! 15146: /* ! 15147: * Clear request microcode control flag. ! 15148: */ ! 15149: scsiq->cntl = 0; ! 15150: ! 15151: /* ! 15152: * Check Condition handling ! 15153: */ ! 15154: if ((scsiq->done_status == QD_WITH_ERROR) && ! 15155: (scsiq->scsi_status == SS_CHK_CONDITION) && ! 15156: (sense_data = (ASC_REQ_SENSE *) scsiq->vsense_addr) != 0 && ! 15157: (scsiq->orig_sense_len - scsiq->sense_len) >= ASC_MIN_SENSE_LEN) ! 15158: { ! 15159: /* ! 15160: * Command returned with a check condition and valid ! 15161: * sense data. ! 15162: */ ! 15163: } ! 15164: /* ! 15165: * If the command that completed was a SCSI INQUIRY and ! 15166: * LUN 0 was sent the command, then process the INQUIRY ! 15167: * command information for the device. ! 15168: */ ! 15169: else if (scsiq->done_status == QD_NO_ERROR && ! 15170: scsiq->cdb[0] == SCSICMD_Inquiry && ! 15171: scsiq->target_lun == 0) ! 15172: { ! 15173: AdvInquiryHandling(asc_dvc, scsiq); ! 15174: } ! 15175: ! 15176: ! 15177: /* Change the RISC Queue List state to free. */ ! 15178: AdvWriteByteLram(iop_base, next_done_loc + RQL_STATE, ASC_MC_QS_FREE); ! 15179: ! 15180: /* Get the RISC Queue List forward pointer. */ ! 15181: AdvReadByteLram(iop_base, next_done_loc + RQL_FWD, completed_q); ! 15182: ! 15183: /* ! 15184: * Notify the driver of the completed request by passing ! 15185: * the ADV_SCSI_REQ_Q pointer to its callback function. ! 15186: */ ! 15187: ADV_ASSERT(asc_dvc->cur_host_qng > 0); ! 15188: asc_dvc->cur_host_qng--; ! 15189: scsiq->a_flag |= ADV_SCSIQ_DONE; ! 15190: (*(ADV_ISR_CALLBACK) asc_dvc->isr_callback)(asc_dvc, scsiq); ! 15191: /* ! 15192: * Note: After the driver callback function is called, 'scsiq' ! 15193: * can no longer be referenced. ! 15194: * ! 15195: * Fall through and continue processing other completed ! 15196: * requests... ! 15197: */ ! 15198: ! 15199: /* ! 15200: * Disable interrupts again in case the driver inadvertently ! 15201: * enabled interrupts in its callback function. ! 15202: * ! 15203: * The DvcEnterCritical() return value is ignored, because ! 15204: * the 'flags' saved when AdvISR() was first entered will be ! 15205: * used to restore the interrupt flag on exit. ! 15206: */ ! 15207: (void) DvcEnterCritical(); ! 15208: } ! 15209: DvcLeaveCritical(flags); ! 15210: return ret; ! 15211: } ! 15212: ! 15213: /* ! 15214: * Send an idle command to the chip and wait for completion. ! 15215: * ! 15216: * Interrupts do not have to be enabled on entry. ! 15217: * ! 15218: * Return Values: ! 15219: * ADV_TRUE - command completed successfully ! 15220: * ADV_FALSE - command failed ! 15221: */ ! 15222: STATIC int ! 15223: AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc, ! 15224: ushort idle_cmd, ! 15225: ulong idle_cmd_parameter, ! 15226: int flags) ! 15227: { ! 15228: int last_int_level; ! 15229: ulong i; ! 15230: AdvPortAddr iop_base; ! 15231: int ret; ! 15232: ! 15233: asc_dvc->idle_cmd_done = 0; ! 15234: ! 15235: last_int_level = DvcEnterCritical(); ! 15236: iop_base = asc_dvc->iop_base; ! 15237: ! 15238: /* ! 15239: * Write the idle command value after the idle command parameter ! 15240: * has been written to avoid a race condition. If the order is not ! 15241: * followed, the microcode may process the idle command before the ! 15242: * parameters have been written to LRAM. ! 15243: */ ! 15244: AdvWriteDWordLram(iop_base, ASC_MC_IDLE_PARA_STAT, idle_cmd_parameter); ! 15245: AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd); ! 15246: DvcLeaveCritical(last_int_level); ! 15247: ! 15248: /* ! 15249: * If the 'flags' argument contains the ADV_NOWAIT flag, then ! 15250: * return with success. ! 15251: */ ! 15252: if (flags & ADV_NOWAIT) ! 15253: { ! 15254: return ADV_TRUE; ! 15255: } ! 15256: ! 15257: for (i = 0; i < SCSI_WAIT_10_SEC * SCSI_MS_PER_SEC; i++) ! 15258: { ! 15259: /* ! 15260: * 'idle_cmd_done' is set by AdvISR(). ! 15261: */ ! 15262: if (asc_dvc->idle_cmd_done) ! 15263: { ! 15264: break; ! 15265: } ! 15266: DvcSleepMilliSecond(1); ! 15267: ! 15268: /* ! 15269: * If interrupts were disabled on entry to AdvSendIdleCmd(), ! 15270: * then they will still be disabled here. Call AdvISR() to ! 15271: * check for the idle command completion. ! 15272: */ ! 15273: (void) AdvISR(asc_dvc); ! 15274: } ! 15275: ! 15276: last_int_level = DvcEnterCritical(); ! 15277: ! 15278: if (asc_dvc->idle_cmd_done == ADV_FALSE) ! 15279: { ! 15280: ADV_ASSERT(0); /* The idle command should never timeout. */ ! 15281: return ADV_FALSE; ! 15282: } else ! 15283: { ! 15284: AdvReadWordLram(iop_base, ASC_MC_IDLE_PARA_STAT, ret); ! 15285: return ret; ! 15286: } ! 15287: } ! 15288: ! 15289: /* ! 15290: * Send the SCSI request block to the adapter ! 15291: * ! 15292: * Each of the 255 Adv Library/Microcode RISC Lists or mailboxes has the ! 15293: * following structure: ! 15294: * ! 15295: * 0: RQL_FWD - RISC list forward pointer (1 byte) ! 15296: * 1: RQL_BWD - RISC list backward pointer (1 byte) ! 15297: * 2: RQL_STATE - RISC list state byte - free, ready, done, aborted (1 byte) ! 15298: * 3: RQL_TID - request target id (1 byte) ! 15299: * 4: RQL_PHYADDR - ADV_SCSI_REQ_Q physical pointer (4 bytes) ! 15300: * ! 15301: * Return: ! 15302: * ADV_SUCCESS(1) - the request is in the mailbox ! 15303: * ADV_BUSY(0) - total request count > 253, try later ! 15304: */ ! 15305: STATIC int ! 15306: AdvSendScsiCmd( ! 15307: ADV_DVC_VAR *asc_dvc, ! 15308: ADV_SCSI_REQ_Q *scsiq) ! 15309: { ! 15310: ushort next_ready_loc; ! 15311: uchar next_ready_loc_fwd; ! 15312: int last_int_level; ! 15313: AdvPortAddr iop_base; ! 15314: long req_size; ! 15315: ulong q_phy_addr; ! 15316: ! 15317: /* ! 15318: * The ADV_SCSI_REQ_Q 'target_id' field should never be equal ! 15319: * to the host adapter ID or exceed ADV_MAX_TID. ! 15320: */ ! 15321: if (scsiq->target_id == asc_dvc->chip_scsi_id || ! 15322: scsiq->target_id > ADV_MAX_TID) ! 15323: { ! 15324: scsiq->host_status = QHSTA_M_INVALID_DEVICE; ! 15325: scsiq->done_status = QD_WITH_ERROR; ! 15326: return ADV_ERROR; ! 15327: } ! 15328: ! 15329: iop_base = asc_dvc->iop_base; ! 15330: ! 15331: last_int_level = DvcEnterCritical(); ! 15332: ! 15333: if (asc_dvc->cur_host_qng >= asc_dvc->max_host_qng) ! 15334: { ! 15335: DvcLeaveCritical(last_int_level); ! 15336: return ADV_BUSY; ! 15337: } else ! 15338: { ! 15339: ADV_ASSERT(asc_dvc->cur_host_qng < ASC_MC_RISC_Q_TOTAL_CNT); ! 15340: asc_dvc->cur_host_qng++; ! 15341: } ! 15342: ! 15343: /* ! 15344: * Clear the ADV_SCSI_REQ_Q done flag. ! 15345: */ ! 15346: scsiq->a_flag &= ~ADV_SCSIQ_DONE; ! 15347: ! 15348: /* ! 15349: * Save the original sense buffer length. ! 15350: * ! 15351: * After the request completes 'sense_len' will be set to the residual ! 15352: * byte count of the Auto-Request Sense if a command returns CHECK ! 15353: * CONDITION and the Sense Data is valid indicated by 'host_status' not ! 15354: * being set to QHSTA_M_AUTO_REQ_SENSE_FAIL. To determine the valid ! 15355: * Sense Data Length subtract 'sense_len' from 'orig_sense_len'. ! 15356: */ ! 15357: scsiq->orig_sense_len = scsiq->sense_len; ! 15358: ! 15359: AdvReadByteLram(iop_base, ASC_MC_HOST_NEXT_READY, next_ready_loc); ! 15360: next_ready_loc = ASC_MC_RISC_Q_LIST_BASE + ! 15361: (next_ready_loc * ASC_MC_RISC_Q_LIST_SIZE); ! 15362: ! 15363: /* ! 15364: * Write the physical address of the Q to the mailbox. ! 15365: * We need to skip the first four bytes, because the microcode ! 15366: * uses them internally for linking Q's together. ! 15367: */ ! 15368: req_size = sizeof(ADV_SCSI_REQ_Q); ! 15369: q_phy_addr = DvcGetPhyAddr(asc_dvc, scsiq, ! 15370: (uchar *) scsiq, &req_size, ! 15371: ADV_IS_SCSIQ_FLAG); ! 15372: ADV_ASSERT(ADV_DWALIGN(q_phy_addr) == q_phy_addr); ! 15373: ADV_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q)); ! 15374: ! 15375: scsiq->scsiq_ptr = (ADV_SCSI_REQ_Q *) scsiq; ! 15376: ! 15377: /* ! 15378: * The RISC list structure, which 'next_ready_loc' is a pointer ! 15379: * to in microcode LRAM, has the format detailed in the comment ! 15380: * header for this function. ! 15381: * ! 15382: * Write the ADV_SCSI_REQ_Q physical pointer to 'next_ready_loc' request. ! 15383: */ ! 15384: AdvWriteDWordLram(iop_base, next_ready_loc + RQL_PHYADDR, q_phy_addr); ! 15385: ! 15386: /* Write target_id to 'next_ready_loc' request. */ ! 15387: AdvWriteByteLram(iop_base, next_ready_loc + RQL_TID, scsiq->target_id); ! 15388: ! 15389: /* ! 15390: * Set the ASC_MC_HOST_NEXT_READY (0x128) microcode variable to ! 15391: * the 'next_ready_loc' request forward pointer. ! 15392: * ! 15393: * Do this *before* changing the 'next_ready_loc' queue to QS_READY. ! 15394: * After the state is changed to QS_READY 'RQL_FWD' will be changed ! 15395: * by the microcode. ! 15396: * ! 15397: * NOTE: The temporary variable 'next_ready_loc_fwd' is required to ! 15398: * prevent some compilers from optimizing out 'AdvReadByteLram()' if ! 15399: * it were used as the 3rd argument to 'AdvWriteByteLram()'. ! 15400: */ ! 15401: AdvReadByteLram(iop_base, next_ready_loc + RQL_FWD, next_ready_loc_fwd); ! 15402: AdvWriteByteLram(iop_base, ASC_MC_HOST_NEXT_READY, next_ready_loc_fwd); ! 15403: ! 15404: /* ! 15405: * Change the state of 'next_ready_loc' request from QS_FREE to ! 15406: * QS_READY which will cause the microcode to pick it up and ! 15407: * execute it. ! 15408: * ! 15409: * Can't reference 'next_ready_loc' after changing the request ! 15410: * state to QS_READY. The microcode now owns the request. ! 15411: */ ! 15412: AdvWriteByteLram(iop_base, next_ready_loc + RQL_STATE, ASC_MC_QS_READY); ! 15413: ! 15414: DvcLeaveCritical(last_int_level); ! 15415: return ADV_SUCCESS; ! 15416: } ! 15417: ! 15418: /* ! 15419: * Inquiry Information Byte 7 Handling ! 15420: * ! 15421: * Handle SCSI Inquiry Command information for a device by setting ! 15422: * microcode operating variables that affect WDTR, SDTR, and Tag ! 15423: * Queuing. ! 15424: */ ! 15425: STATIC void ! 15426: AdvInquiryHandling( ! 15427: ADV_DVC_VAR *asc_dvc, ! 15428: ADV_SCSI_REQ_Q *scsiq) ! 15429: { ! 15430: AdvPortAddr iop_base; ! 15431: uchar tid; ! 15432: ASC_SCSI_INQUIRY *inq; ! 15433: ushort tidmask; ! 15434: ushort cfg_word; ! 15435: ! 15436: /* ! 15437: * AdvInquiryHandling() requires up to INQUIRY information Byte 7 ! 15438: * to be available. ! 15439: * ! 15440: * If less than 8 bytes of INQUIRY information were requested or less ! 15441: * than 8 bytes were transferred, then return. cdb[4] is the request ! 15442: * length and the ADV_SCSI_REQ_Q 'data_cnt' field is set by the ! 15443: * microcode to the transfer residual count. ! 15444: */ ! 15445: if (scsiq->cdb[4] < 8 || (scsiq->cdb[4] - scsiq->data_cnt) < 8) ! 15446: { ! 15447: return; ! 15448: } ! 15449: ! 15450: iop_base = asc_dvc->iop_base; ! 15451: tid = scsiq->target_id; ! 15452: inq = (ASC_SCSI_INQUIRY *) scsiq->vdata_addr; ! 15453: ! 15454: /* ! 15455: * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices. ! 15456: */ ! 15457: if (inq->byte3.rsp_data_fmt < 2 && inq->byte2.ansi_apr_ver < 2) ! 15458: { ! 15459: return; ! 15460: } else ! 15461: { ! 15462: /* ! 15463: * INQUIRY Byte 7 Handling ! 15464: * ! 15465: * Use a device's INQUIRY byte 7 to determine whether it ! 15466: * supports WDTR, SDTR, and Tag Queuing. If the feature ! 15467: * is enabled in the EEPROM and the device supports the ! 15468: * feature, then enable it in the microcode. ! 15469: */ ! 15470: ! 15471: tidmask = ADV_TID_TO_TIDMASK(tid); ! 15472: ! 15473: /* ! 15474: * Wide Transfers ! 15475: * ! 15476: * If the EEPROM enabled WDTR for the device and the device ! 15477: * supports wide bus (16 bit) transfers, then turn on the ! 15478: * device's 'wdtr_able' bit and write the new value to the ! 15479: * microcode. ! 15480: */ ! 15481: if ((asc_dvc->wdtr_able & tidmask) && inq->byte7.WBus16) ! 15482: { ! 15483: AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); ! 15484: if ((cfg_word & tidmask) == 0) ! 15485: { ! 15486: cfg_word |= tidmask; ! 15487: AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); ! 15488: ! 15489: /* ! 15490: * Clear the microcode "WDTR negotiation" done indicator ! 15491: * for the target to cause it to negotiate with the new ! 15492: * setting set above. ! 15493: */ ! 15494: AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word); ! 15495: cfg_word &= ~tidmask; ! 15496: AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word); ! 15497: } ! 15498: } ! 15499: ! 15500: /* ! 15501: * Synchronous Transfers ! 15502: * ! 15503: * If the EEPROM enabled SDTR for the device and the device ! 15504: * supports synchronous transfers, then turn on the device's ! 15505: * 'sdtr_able' bit. Write the new value to the microcode. ! 15506: */ ! 15507: if ((asc_dvc->sdtr_able & tidmask) && inq->byte7.Sync) ! 15508: { ! 15509: AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); ! 15510: if ((cfg_word & tidmask) == 0) ! 15511: { ! 15512: cfg_word |= tidmask; ! 15513: AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); ! 15514: ! 15515: /* ! 15516: * Clear the microcode "SDTR negotiation" done indicator ! 15517: * for the target to cause it to negotiate with the new ! 15518: * setting set above. ! 15519: */ ! 15520: AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); ! 15521: cfg_word &= ~tidmask; ! 15522: AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); ! 15523: } ! 15524: } ! 15525: ! 15526: /* ! 15527: * If the EEPROM enabled Tag Queuing for device and the ! 15528: * device supports Tag Queuing, then turn on the device's ! 15529: * 'tagqng_enable' bit in the microcode and set the microcode ! 15530: * maximum command count to the ADV_DVC_VAR 'max_dvc_qng' ! 15531: * value. ! 15532: * ! 15533: * Tag Queuing is disabled for the BIOS which runs in polled ! 15534: * mode and would see no benefit from Tag Queuing. Also by ! 15535: * disabling Tag Queuing in the BIOS devices with Tag Queuing ! 15536: * bugs will at least work with the BIOS. ! 15537: */ ! 15538: if ((asc_dvc->tagqng_able & tidmask) && inq->byte7.CmdQue) ! 15539: { ! 15540: AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word); ! 15541: cfg_word |= tidmask; ! 15542: AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word); ! 15543: AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, ! 15544: asc_dvc->max_dvc_qng); ! 15545: } ! 15546: } ! 15547: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.