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