|
|
1.1 ! root 1: /* ! 2: * QLogic ISP1020 Intelligent SCSI Processor Driver (PCI) ! 3: * Written by Erik H. Moe, [email protected] ! 4: * Copyright 1995, Erik H. Moe ! 5: * ! 6: * This program is free software; you can redistribute it and/or modify it ! 7: * under the terms of the GNU General Public License as published by the ! 8: * Free Software Foundation; either version 2, or (at your option) any ! 9: * later version. ! 10: * ! 11: * This program is distributed in the hope that it will be useful, but ! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 14: * General Public License for more details. ! 15: */ ! 16: ! 17: /* Renamed and updated to 1.3.x by Michael Griffith <[email protected]> */ ! 18: ! 19: /* ! 20: * $Date: 1999/04/26 05:54:52 $ ! 21: * $Revision: 1.1 $ ! 22: * ! 23: * $Log: qlogicisp.c,v $ ! 24: * Revision 1.1 1999/04/26 05:54:52 tb ! 25: * 1998-11-30 OKUJI Yoshinori <[email protected]> ! 26: * ! 27: * Clean up linux emulation code to make it architecture-independent ! 28: * as much as possible. ! 29: * ! 30: * * linux: Renamed from linuxdev. ! 31: * * Makefile.in (objfiles): Add linux.o instead of linuxdev.o. ! 32: * (MAKE): New variable. Used for the linux.o target. ! 33: * * configure.in: Add AC_CHECK_TOOL(MAKE, make). ! 34: * * i386/i386/spl.h: Include <i386/ipl.h>, for compatibility with ! 35: * OSF Mach 3.0. Suggested by Elgin Lee <[email protected]>. ! 36: * * linux/src: Renamed from linux/linux. ! 37: * * linux/dev: Renamed from linux/mach. ! 38: * * linux/Drivers.in (AC_INIT): Use dev/include/linux/autoconf.h, ! 39: * instead of mach/include/linux/autoconf.h. ! 40: * * Makefile.in (all): Target ../linux.o instead of ../linuxdev.o. ! 41: * * linux/dev/drivers/block/genhd.c: Include <machine/spl.h> instead ! 42: * of <i386/ipl.h>. ! 43: * * linux/dev/drivers/net/auto_irq.c: Remove unneeded header files, ! 44: * <i386/ipl.h> and <i386/pic.h>. ! 45: * * linux/dev/init/main.c: Many i386-dependent codes moved to ... ! 46: * * linux/dev/arch/i386/irq.c: ... here. ! 47: * * linux/dev/arch/i386/setup.c: New file. ! 48: * * linux/dev/arch/i386/linux_emul.h: Likewise. ! 49: * * linux/dev/arch/i386/glue/timer.c: Merged into sched.c. ! 50: * * linux/dev/arch/i386/glue/sched.c: Include <machine/spl.h> instead ! 51: * of <i386/ipl.h>, and moved to ... ! 52: * * linux/dev/kernel/sched.c: ... here. ! 53: * * linux/dev/arch/i386/glue/block.c: Include <machine/spl.h> and ! 54: * <linux_emul.h>, instead of i386-dependent header files, and ! 55: * moved to ... ! 56: * * linux/dev/glue/blocl.c: ... here. ! 57: * * linux/dev/arch/i386/glue/net.c: Include <machine/spl.h> and ! 58: * <linux_emul.h>, instead of i386-dependent header files, and ! 59: * moved to ... ! 60: * * linux/dev/glue/net.c: ... here. ! 61: * * linux/dev/arch/i386/glue/misc.c: Remove `x86' and moved to ... ! 62: * * linux/dev/glue/misc.c: ... here. ! 63: * * linux/dev/arch/i386/glue/kmem.c: Moved to ... ! 64: * * linux/dev/glue/kmem.c: ... here. ! 65: * ! 66: * Revision 0.5 1995/09/22 02:23:15 root ! 67: * do auto request sense ! 68: * ! 69: * Revision 0.4 1995/08/07 04:44:33 root ! 70: * supply firmware with driver. ! 71: * numerous bug fixes/general cleanup of code. ! 72: * ! 73: * Revision 0.3 1995/07/16 16:15:39 root ! 74: * added reset/abort code. ! 75: * ! 76: * Revision 0.2 1995/06/29 03:14:19 root ! 77: * fixed biosparam. ! 78: * added queue protocol. ! 79: * ! 80: * Revision 0.1 1995/06/25 01:55:45 root ! 81: * Initial release. ! 82: * ! 83: */ ! 84: ! 85: #include <linux/blk.h> ! 86: #include <linux/kernel.h> ! 87: #include <linux/string.h> ! 88: #include <linux/ioport.h> ! 89: #include <linux/sched.h> ! 90: #include <linux/types.h> ! 91: #include <linux/bios32.h> ! 92: #include <linux/pci.h> ! 93: #include <linux/delay.h> ! 94: #include <linux/unistd.h> ! 95: #include <asm/io.h> ! 96: #include <asm/irq.h> ! 97: ! 98: #include "sd.h" ! 99: #include "hosts.h" ! 100: #include "qlogicisp.h" ! 101: ! 102: /* Configuration section *****************************************************/ ! 103: ! 104: /* Set the following macro to 1 to reload the ISP1020's firmware. This is ! 105: the latest firmware provided by QLogic. This may be an earlier/later ! 106: revision than supplied by your board. */ ! 107: ! 108: #define RELOAD_FIRMWARE 1 ! 109: ! 110: /* Set the following macro to 1 to reload the ISP1020's defaults from nvram. ! 111: If you are not sure of your settings, leave this alone, the driver will ! 112: use a set of 'safe' defaults */ ! 113: ! 114: #define USE_NVRAM_DEFAULTS 0 ! 115: ! 116: /* Macros used for debugging */ ! 117: ! 118: #define DEBUG_ISP1020 0 ! 119: #define DEBUG_ISP1020_INT 0 ! 120: #define DEBUG_ISP1020_SETUP 0 ! 121: #define TRACE_ISP 0 ! 122: ! 123: #define DEFAULT_LOOP_COUNT 1000000 ! 124: ! 125: /* End Configuration section *************************************************/ ! 126: ! 127: #include <linux/module.h> ! 128: ! 129: #if TRACE_ISP ! 130: ! 131: # define TRACE_BUF_LEN (32*1024) ! 132: ! 133: struct { ! 134: u_long next; ! 135: struct { ! 136: u_long time; ! 137: u_int index; ! 138: u_int addr; ! 139: u_char * name; ! 140: } buf[TRACE_BUF_LEN]; ! 141: } trace; ! 142: ! 143: #define TRACE(w, i, a) \ ! 144: { \ ! 145: unsigned long flags; \ ! 146: \ ! 147: save_flags(flags); \ ! 148: cli(); \ ! 149: trace.buf[trace.next].name = (w); \ ! 150: trace.buf[trace.next].time = jiffies; \ ! 151: trace.buf[trace.next].index = (i); \ ! 152: trace.buf[trace.next].addr = (long) (a); \ ! 153: trace.next = (trace.next + 1) & (TRACE_BUF_LEN - 1); \ ! 154: restore_flags(flags); \ ! 155: } ! 156: ! 157: #else ! 158: # define TRACE(w, i, a) ! 159: #endif ! 160: ! 161: #if DEBUG_ISP1020 ! 162: #define ENTER(x) printk("isp1020 : entering %s()\n", x); ! 163: #define LEAVE(x) printk("isp1020 : leaving %s()\n", x); ! 164: #define DEBUG(x) x ! 165: #else ! 166: #define ENTER(x) ! 167: #define LEAVE(x) ! 168: #define DEBUG(x) ! 169: #endif /* DEBUG_ISP1020 */ ! 170: ! 171: #if DEBUG_ISP1020_INTR ! 172: #define ENTER_INTR(x) printk("isp1020 : entering %s()\n", x); ! 173: #define LEAVE_INTR(x) printk("isp1020 : leaving %s()\n", x); ! 174: #define DEBUG_INTR(x) x ! 175: #else ! 176: #define ENTER_INTR(x) ! 177: #define LEAVE_INTR(x) ! 178: #define DEBUG_INTR(x) ! 179: #endif /* DEBUG ISP1020_INTR */ ! 180: ! 181: #define ISP1020_REV_ID 1 ! 182: ! 183: #define MAX_TARGETS 16 ! 184: #define MAX_LUNS 8 ! 185: ! 186: /* host configuration and control registers */ ! 187: #define HOST_HCCR 0xc0 /* host command and control */ ! 188: ! 189: /* pci bus interface registers */ ! 190: #define PCI_ID_LOW 0x00 /* vendor id */ ! 191: #define PCI_ID_HIGH 0x02 /* device id */ ! 192: #define ISP_CFG0 0x04 /* configuration register #0 */ ! 193: #define ISP_CFG1 0x06 /* configuration register #1 */ ! 194: #define PCI_INTF_CTL 0x08 /* pci interface control */ ! 195: #define PCI_INTF_STS 0x0a /* pci interface status */ ! 196: #define PCI_SEMAPHORE 0x0c /* pci semaphore */ ! 197: #define PCI_NVRAM 0x0e /* pci nvram interface */ ! 198: ! 199: /* mailbox registers */ ! 200: #define MBOX0 0x70 /* mailbox 0 */ ! 201: #define MBOX1 0x72 /* mailbox 1 */ ! 202: #define MBOX2 0x74 /* mailbox 2 */ ! 203: #define MBOX3 0x76 /* mailbox 3 */ ! 204: #define MBOX4 0x78 /* mailbox 4 */ ! 205: #define MBOX5 0x7a /* mailbox 5 */ ! 206: ! 207: /* mailbox command complete status codes */ ! 208: #define MBOX_COMMAND_COMPLETE 0x4000 ! 209: #define INVALID_COMMAND 0x4001 ! 210: #define HOST_INTERFACE_ERROR 0x4002 ! 211: #define TEST_FAILED 0x4003 ! 212: #define COMMAND_ERROR 0x4005 ! 213: #define COMMAND_PARAM_ERROR 0x4006 ! 214: ! 215: /* async event status codes */ ! 216: #define ASYNC_SCSI_BUS_RESET 0x8001 ! 217: #define SYSTEM_ERROR 0x8002 ! 218: #define REQUEST_TRANSFER_ERROR 0x8003 ! 219: #define RESPONSE_TRANSFER_ERROR 0x8004 ! 220: #define REQUEST_QUEUE_WAKEUP 0x8005 ! 221: #define EXECUTION_TIMEOUT_RESET 0x8006 ! 222: ! 223: struct Entry_header { ! 224: u_char entry_type; ! 225: u_char entry_cnt; ! 226: u_char sys_def_1; ! 227: u_char flags; ! 228: }; ! 229: ! 230: /* entry header type commands */ ! 231: #define ENTRY_COMMAND 1 ! 232: #define ENTRY_CONTINUATION 2 ! 233: #define ENTRY_STATUS 3 ! 234: #define ENTRY_MARKER 4 ! 235: #define ENTRY_EXTENDED_COMMAND 5 ! 236: ! 237: /* entry header flag definitions */ ! 238: #define EFLAG_CONTINUATION 1 ! 239: #define EFLAG_BUSY 2 ! 240: #define EFLAG_BAD_HEADER 4 ! 241: #define EFLAG_BAD_PAYLOAD 8 ! 242: ! 243: struct dataseg { ! 244: u_int d_base; ! 245: u_int d_count; ! 246: }; ! 247: ! 248: struct Command_Entry { ! 249: struct Entry_header hdr; ! 250: u_int handle; ! 251: u_char target_lun; ! 252: u_char target_id; ! 253: u_short cdb_length; ! 254: u_short control_flags; ! 255: u_short rsvd; ! 256: u_short time_out; ! 257: u_short segment_cnt; ! 258: u_char cdb[12]; ! 259: struct dataseg dataseg[4]; ! 260: }; ! 261: ! 262: /* command entry control flag definitions */ ! 263: #define CFLAG_NODISC 0x01 ! 264: #define CFLAG_HEAD_TAG 0x02 ! 265: #define CFLAG_ORDERED_TAG 0x04 ! 266: #define CFLAG_SIMPLE_TAG 0x08 ! 267: #define CFLAG_TAR_RTN 0x10 ! 268: #define CFLAG_READ 0x20 ! 269: #define CFLAG_WRITE 0x40 ! 270: ! 271: struct Ext_Command_Entry { ! 272: struct Entry_header hdr; ! 273: u_int handle; ! 274: u_char target_lun; ! 275: u_char target_id; ! 276: u_short cdb_length; ! 277: u_short control_flags; ! 278: u_short rsvd; ! 279: u_short time_out; ! 280: u_short segment_cnt; ! 281: u_char cdb[44]; ! 282: }; ! 283: ! 284: struct Continuation_Entry { ! 285: struct Entry_header hdr; ! 286: u_int reserved; ! 287: struct dataseg dataseg[7]; ! 288: }; ! 289: ! 290: struct Marker_Entry { ! 291: struct Entry_header hdr; ! 292: u_int reserved; ! 293: u_char target_lun; ! 294: u_char target_id; ! 295: u_char modifier; ! 296: u_char rsvd; ! 297: u_char rsvds[52]; ! 298: }; ! 299: ! 300: /* marker entry modifier definitions */ ! 301: #define SYNC_DEVICE 0 ! 302: #define SYNC_TARGET 1 ! 303: #define SYNC_ALL 2 ! 304: ! 305: struct Status_Entry { ! 306: struct Entry_header hdr; ! 307: u_int handle; ! 308: u_short scsi_status; ! 309: u_short completion_status; ! 310: u_short state_flags; ! 311: u_short status_flags; ! 312: u_short time; ! 313: u_short req_sense_len; ! 314: u_int residual; ! 315: u_char rsvd[8]; ! 316: u_char req_sense_data[32]; ! 317: }; ! 318: ! 319: /* status entry completion status definitions */ ! 320: #define CS_COMPLETE 0x0000 ! 321: #define CS_INCOMPLETE 0x0001 ! 322: #define CS_DMA_ERROR 0x0002 ! 323: #define CS_TRANSPORT_ERROR 0x0003 ! 324: #define CS_RESET_OCCURRED 0x0004 ! 325: #define CS_ABORTED 0x0005 ! 326: #define CS_TIMEOUT 0x0006 ! 327: #define CS_DATA_OVERRUN 0x0007 ! 328: #define CS_COMMAND_OVERRUN 0x0008 ! 329: #define CS_STATUS_OVERRUN 0x0009 ! 330: #define CS_BAD_MESSAGE 0x000a ! 331: #define CS_NO_MESSAGE_OUT 0x000b ! 332: #define CS_EXT_ID_FAILED 0x000c ! 333: #define CS_IDE_MSG_FAILED 0x000d ! 334: #define CS_ABORT_MSG_FAILED 0x000e ! 335: #define CS_REJECT_MSG_FAILED 0x000f ! 336: #define CS_NOP_MSG_FAILED 0x0010 ! 337: #define CS_PARITY_ERROR_MSG_FAILED 0x0011 ! 338: #define CS_DEVICE_RESET_MSG_FAILED 0x0012 ! 339: #define CS_ID_MSG_FAILED 0x0013 ! 340: #define CS_UNEXP_BUS_FREE 0x0014 ! 341: /* as per app note #83120-514-06a: */ ! 342: #define CS_DATA_UNDERRUN 0x0015 ! 343: #define CS_INVALID_ENTRY_TYPE 0x001b ! 344: #define CS_DEVICE_QUEUE_FULL 0x001c ! 345: #define CS_SCSI_PHASE_SKIPPED 0x001d ! 346: #define CS_ARS_FAILED 0x001e /* auto Req. Sense failed */ ! 347: ! 348: /* status entry state flag definitions */ ! 349: #define SF_GOT_BUS 0x0100 ! 350: #define SF_GOT_TARGET 0x0200 ! 351: #define SF_SENT_CDB 0x0400 ! 352: #define SF_TRANSFERRED_DATA 0x0800 ! 353: #define SF_GOT_STATUS 0x1000 ! 354: #define SF_GOT_SENSE 0x2000 ! 355: ! 356: /* status entry status flag definitions */ ! 357: #define STF_DISCONNECT 0x0001 ! 358: #define STF_SYNCHRONOUS 0x0002 ! 359: #define STF_PARITY_ERROR 0x0004 ! 360: #define STF_BUS_RESET 0x0008 ! 361: #define STF_DEVICE_RESET 0x0010 ! 362: #define STF_ABORTED 0x0020 ! 363: #define STF_TIMEOUT 0x0040 ! 364: #define STF_NEGOTIATION 0x0080 ! 365: ! 366: /* interface control commands */ ! 367: #define ISP_RESET 0x0001 ! 368: #define ISP_EN_INT 0x0002 ! 369: #define ISP_EN_RISC 0x0004 ! 370: ! 371: /* host control commands */ ! 372: #define HCCR_NOP 0x0000 ! 373: #define HCCR_RESET 0x1000 ! 374: #define HCCR_PAUSE 0x2000 ! 375: #define HCCR_RELEASE 0x3000 ! 376: #define HCCR_SINGLE_STEP 0x4000 ! 377: #define HCCR_SET_HOST_INTR 0x5000 ! 378: #define HCCR_CLEAR_HOST_INTR 0x6000 ! 379: #define HCCR_CLEAR_RISC_INTR 0x7000 ! 380: #define HCCR_BP_ENABLE 0x8000 ! 381: #define HCCR_BIOS_DISABLE 0x9000 ! 382: #define HCCR_TEST_MODE 0xf000 ! 383: ! 384: #define RISC_BUSY 0x0004 ! 385: ! 386: /* mailbox commands */ ! 387: #define MBOX_NO_OP 0x0000 ! 388: #define MBOX_LOAD_RAM 0x0001 ! 389: #define MBOX_EXEC_FIRMWARE 0x0002 ! 390: #define MBOX_DUMP_RAM 0x0003 ! 391: #define MBOX_WRITE_RAM_WORD 0x0004 ! 392: #define MBOX_READ_RAM_WORD 0x0005 ! 393: #define MBOX_MAILBOX_REG_TEST 0x0006 ! 394: #define MBOX_VERIFY_CHECKSUM 0x0007 ! 395: #define MBOX_ABOUT_FIRMWARE 0x0008 ! 396: #define MBOX_CHECK_FIRMWARE 0x000e ! 397: #define MBOX_INIT_REQ_QUEUE 0x0010 ! 398: #define MBOX_INIT_RES_QUEUE 0x0011 ! 399: #define MBOX_EXECUTE_IOCB 0x0012 ! 400: #define MBOX_WAKE_UP 0x0013 ! 401: #define MBOX_STOP_FIRMWARE 0x0014 ! 402: #define MBOX_ABORT 0x0015 ! 403: #define MBOX_ABORT_DEVICE 0x0016 ! 404: #define MBOX_ABORT_TARGET 0x0017 ! 405: #define MBOX_BUS_RESET 0x0018 ! 406: #define MBOX_STOP_QUEUE 0x0019 ! 407: #define MBOX_START_QUEUE 0x001a ! 408: #define MBOX_SINGLE_STEP_QUEUE 0x001b ! 409: #define MBOX_ABORT_QUEUE 0x001c ! 410: #define MBOX_GET_DEV_QUEUE_STATUS 0x001d ! 411: #define MBOX_GET_FIRMWARE_STATUS 0x001f ! 412: #define MBOX_GET_INIT_SCSI_ID 0x0020 ! 413: #define MBOX_GET_SELECT_TIMEOUT 0x0021 ! 414: #define MBOX_GET_RETRY_COUNT 0x0022 ! 415: #define MBOX_GET_TAG_AGE_LIMIT 0x0023 ! 416: #define MBOX_GET_CLOCK_RATE 0x0024 ! 417: #define MBOX_GET_ACT_NEG_STATE 0x0025 ! 418: #define MBOX_GET_ASYNC_DATA_SETUP_TIME 0x0026 ! 419: #define MBOX_GET_PCI_PARAMS 0x0027 ! 420: #define MBOX_GET_TARGET_PARAMS 0x0028 ! 421: #define MBOX_GET_DEV_QUEUE_PARAMS 0x0029 ! 422: #define MBOX_SET_INIT_SCSI_ID 0x0030 ! 423: #define MBOX_SET_SELECT_TIMEOUT 0x0031 ! 424: #define MBOX_SET_RETRY_COUNT 0x0032 ! 425: #define MBOX_SET_TAG_AGE_LIMIT 0x0033 ! 426: #define MBOX_SET_CLOCK_RATE 0x0034 ! 427: #define MBOX_SET_ACTIVE_NEG_STATE 0x0035 ! 428: #define MBOX_SET_ASYNC_DATA_SETUP_TIME 0x0036 ! 429: #define MBOX_SET_PCI_CONTROL_PARAMS 0x0037 ! 430: #define MBOX_SET_TARGET_PARAMS 0x0038 ! 431: #define MBOX_SET_DEV_QUEUE_PARAMS 0x0039 ! 432: #define MBOX_RETURN_BIOS_BLOCK_ADDR 0x0040 ! 433: #define MBOX_WRITE_FOUR_RAM_WORDS 0x0041 ! 434: #define MBOX_EXEC_BIOS_IOCB 0x0042 ! 435: ! 436: #include "qlogicisp_asm.c" ! 437: ! 438: #define PACKB(a, b) (((a)<<4)|(b)) ! 439: ! 440: const u_char mbox_param[] = { ! 441: PACKB(1, 1), /* MBOX_NO_OP */ ! 442: PACKB(5, 5), /* MBOX_LOAD_RAM */ ! 443: PACKB(2, 0), /* MBOX_EXEC_FIRMWARE */ ! 444: PACKB(5, 5), /* MBOX_DUMP_RAM */ ! 445: PACKB(3, 3), /* MBOX_WRITE_RAM_WORD */ ! 446: PACKB(2, 3), /* MBOX_READ_RAM_WORD */ ! 447: PACKB(6, 6), /* MBOX_MAILBOX_REG_TEST */ ! 448: PACKB(2, 3), /* MBOX_VERIFY_CHECKSUM */ ! 449: PACKB(1, 3), /* MBOX_ABOUT_FIRMWARE */ ! 450: PACKB(0, 0), /* 0x0009 */ ! 451: PACKB(0, 0), /* 0x000a */ ! 452: PACKB(0, 0), /* 0x000b */ ! 453: PACKB(0, 0), /* 0x000c */ ! 454: PACKB(0, 0), /* 0x000d */ ! 455: PACKB(1, 2), /* MBOX_CHECK_FIRMWARE */ ! 456: PACKB(0, 0), /* 0x000f */ ! 457: PACKB(5, 5), /* MBOX_INIT_REQ_QUEUE */ ! 458: PACKB(6, 6), /* MBOX_INIT_RES_QUEUE */ ! 459: PACKB(4, 4), /* MBOX_EXECUTE_IOCB */ ! 460: PACKB(2, 2), /* MBOX_WAKE_UP */ ! 461: PACKB(1, 6), /* MBOX_STOP_FIRMWARE */ ! 462: PACKB(4, 4), /* MBOX_ABORT */ ! 463: PACKB(2, 2), /* MBOX_ABORT_DEVICE */ ! 464: PACKB(3, 3), /* MBOX_ABORT_TARGET */ ! 465: PACKB(2, 2), /* MBOX_BUS_RESET */ ! 466: PACKB(2, 3), /* MBOX_STOP_QUEUE */ ! 467: PACKB(2, 3), /* MBOX_START_QUEUE */ ! 468: PACKB(2, 3), /* MBOX_SINGLE_STEP_QUEUE */ ! 469: PACKB(2, 3), /* MBOX_ABORT_QUEUE */ ! 470: PACKB(2, 4), /* MBOX_GET_DEV_QUEUE_STATUS */ ! 471: PACKB(0, 0), /* 0x001e */ ! 472: PACKB(1, 3), /* MBOX_GET_FIRMWARE_STATUS */ ! 473: PACKB(1, 2), /* MBOX_GET_INIT_SCSI_ID */ ! 474: PACKB(1, 2), /* MBOX_GET_SELECT_TIMEOUT */ ! 475: PACKB(1, 3), /* MBOX_GET_RETRY_COUNT */ ! 476: PACKB(1, 2), /* MBOX_GET_TAG_AGE_LIMIT */ ! 477: PACKB(1, 2), /* MBOX_GET_CLOCK_RATE */ ! 478: PACKB(1, 2), /* MBOX_GET_ACT_NEG_STATE */ ! 479: PACKB(1, 2), /* MBOX_GET_ASYNC_DATA_SETUP_TIME */ ! 480: PACKB(1, 3), /* MBOX_GET_PCI_PARAMS */ ! 481: PACKB(2, 4), /* MBOX_GET_TARGET_PARAMS */ ! 482: PACKB(2, 4), /* MBOX_GET_DEV_QUEUE_PARAMS */ ! 483: PACKB(0, 0), /* 0x002a */ ! 484: PACKB(0, 0), /* 0x002b */ ! 485: PACKB(0, 0), /* 0x002c */ ! 486: PACKB(0, 0), /* 0x002d */ ! 487: PACKB(0, 0), /* 0x002e */ ! 488: PACKB(0, 0), /* 0x002f */ ! 489: PACKB(2, 2), /* MBOX_SET_INIT_SCSI_ID */ ! 490: PACKB(2, 2), /* MBOX_SET_SELECT_TIMEOUT */ ! 491: PACKB(3, 3), /* MBOX_SET_RETRY_COUNT */ ! 492: PACKB(2, 2), /* MBOX_SET_TAG_AGE_LIMIT */ ! 493: PACKB(2, 2), /* MBOX_SET_CLOCK_RATE */ ! 494: PACKB(2, 2), /* MBOX_SET_ACTIVE_NEG_STATE */ ! 495: PACKB(2, 2), /* MBOX_SET_ASYNC_DATA_SETUP_TIME */ ! 496: PACKB(3, 3), /* MBOX_SET_PCI_CONTROL_PARAMS */ ! 497: PACKB(4, 4), /* MBOX_SET_TARGET_PARAMS */ ! 498: PACKB(4, 4), /* MBOX_SET_DEV_QUEUE_PARAMS */ ! 499: PACKB(0, 0), /* 0x003a */ ! 500: PACKB(0, 0), /* 0x003b */ ! 501: PACKB(0, 0), /* 0x003c */ ! 502: PACKB(0, 0), /* 0x003d */ ! 503: PACKB(0, 0), /* 0x003e */ ! 504: PACKB(0, 0), /* 0x003f */ ! 505: PACKB(1, 2), /* MBOX_RETURN_BIOS_BLOCK_ADDR */ ! 506: PACKB(6, 1), /* MBOX_WRITE_FOUR_RAM_WORDS */ ! 507: PACKB(2, 3) /* MBOX_EXEC_BIOS_IOCB */ ! 508: }; ! 509: ! 510: #define MAX_MBOX_COMMAND (sizeof(mbox_param)/sizeof(u_short)) ! 511: ! 512: struct host_param { ! 513: u_short fifo_threshold; ! 514: u_short host_adapter_enable; ! 515: u_short initiator_scsi_id; ! 516: u_short bus_reset_delay; ! 517: u_short retry_count; ! 518: u_short retry_delay; ! 519: u_short async_data_setup_time; ! 520: u_short req_ack_active_negation; ! 521: u_short data_line_active_negation; ! 522: u_short data_dma_burst_enable; ! 523: u_short command_dma_burst_enable; ! 524: u_short tag_aging; ! 525: u_short selection_timeout; ! 526: u_short max_queue_depth; ! 527: }; ! 528: ! 529: /* ! 530: * Device Flags: ! 531: * ! 532: * Bit Name ! 533: * --------- ! 534: * 7 Disconnect Privilege ! 535: * 6 Parity Checking ! 536: * 5 Wide Data Transfers ! 537: * 4 Synchronous Data Transfers ! 538: * 3 Tagged Queuing ! 539: * 2 Automatic Request Sense ! 540: * 1 Stop Queue on Check Condition ! 541: * 0 Renegotiate on Error ! 542: */ ! 543: ! 544: struct dev_param { ! 545: u_short device_flags; ! 546: u_short execution_throttle; ! 547: u_short synchronous_period; ! 548: u_short synchronous_offset; ! 549: u_short device_enable; ! 550: u_short reserved; /* pad */ ! 551: }; ! 552: ! 553: /* ! 554: * The result queue can be quite a bit smaller since continuation entries ! 555: * do not show up there: ! 556: */ ! 557: #define RES_QUEUE_LEN ((QLOGICISP_REQ_QUEUE_LEN + 1) / 8 - 1) ! 558: #define QUEUE_ENTRY_LEN 64 ! 559: ! 560: struct isp1020_hostdata { ! 561: u_char bus; ! 562: u_char revision; ! 563: u_char device_fn; ! 564: struct host_param host_param; ! 565: struct dev_param dev_param[MAX_TARGETS]; ! 566: ! 567: /* result and request queues (shared with isp1020): */ ! 568: u_int req_in_ptr; /* index of next request slot */ ! 569: u_int res_out_ptr; /* index of next result slot */ ! 570: ! 571: /* this is here so the queues are nicely aligned */ ! 572: long send_marker; /* do we need to send a marker? */ ! 573: ! 574: char res[RES_QUEUE_LEN+1][QUEUE_ENTRY_LEN]; ! 575: char req[QLOGICISP_REQ_QUEUE_LEN+1][QUEUE_ENTRY_LEN]; ! 576: }; ! 577: ! 578: /* queue length's _must_ be power of two: */ ! 579: #define QUEUE_DEPTH(in, out, ql) ((in - out) & (ql)) ! 580: #define REQ_QUEUE_DEPTH(in, out) QUEUE_DEPTH(in, out, \ ! 581: QLOGICISP_REQ_QUEUE_LEN) ! 582: #define RES_QUEUE_DEPTH(in, out) QUEUE_DEPTH(in, out, RES_QUEUE_LEN) ! 583: ! 584: struct Scsi_Host *irq2host[NR_IRQS]; ! 585: ! 586: static void isp1020_enable_irqs(struct Scsi_Host *); ! 587: static void isp1020_disable_irqs(struct Scsi_Host *); ! 588: static int isp1020_init(struct Scsi_Host *); ! 589: static int isp1020_reset_hardware(struct Scsi_Host *); ! 590: static int isp1020_set_defaults(struct Scsi_Host *); ! 591: static int isp1020_load_parameters(struct Scsi_Host *); ! 592: static int isp1020_mbox_command(struct Scsi_Host *, u_short []); ! 593: static int isp1020_return_status(struct Status_Entry *); ! 594: static void isp1020_intr_handler(int, void *, struct pt_regs *); ! 595: ! 596: #if USE_NVRAM_DEFAULTS ! 597: static int isp1020_get_defaults(struct Scsi_Host *); ! 598: static int isp1020_verify_nvram(struct Scsi_Host *); ! 599: static u_short isp1020_read_nvram_word(struct Scsi_Host *, u_short); ! 600: #endif ! 601: ! 602: #if DEBUG_ISP1020 ! 603: static void isp1020_print_scsi_cmd(Scsi_Cmnd *); ! 604: #endif ! 605: #if DEBUG_ISP1020_INTR ! 606: static void isp1020_print_status_entry(struct Status_Entry *); ! 607: #endif ! 608: ! 609: static struct proc_dir_entry proc_scsi_isp1020 = { ! 610: PROC_SCSI_QLOGICISP, 7, "isp1020", ! 611: S_IFDIR | S_IRUGO | S_IXUGO, 2 ! 612: }; ! 613: ! 614: ! 615: static inline void isp1020_enable_irqs(struct Scsi_Host *host) ! 616: { ! 617: outw(ISP_EN_INT|ISP_EN_RISC, host->io_port + PCI_INTF_CTL); ! 618: } ! 619: ! 620: ! 621: static inline void isp1020_disable_irqs(struct Scsi_Host *host) ! 622: { ! 623: outw(0x0, host->io_port + PCI_INTF_CTL); ! 624: } ! 625: ! 626: ! 627: int isp1020_detect(Scsi_Host_Template *tmpt) ! 628: { ! 629: int hosts = 0; ! 630: u_short index; ! 631: u_char bus, device_fn; ! 632: struct Scsi_Host *host; ! 633: struct isp1020_hostdata *hostdata; ! 634: ! 635: ENTER("isp1020_detect"); ! 636: ! 637: tmpt->proc_dir = &proc_scsi_isp1020; ! 638: ! 639: if (pcibios_present() == 0) { ! 640: printk("qlogicisp : PCI bios not present\n"); ! 641: return 0; ! 642: } ! 643: ! 644: memset(irq2host, 0, sizeof(irq2host)); ! 645: ! 646: for (index = 0; pcibios_find_device(PCI_VENDOR_ID_QLOGIC, ! 647: PCI_DEVICE_ID_QLOGIC_ISP1020, ! 648: index, &bus, &device_fn) == 0; ! 649: index++) ! 650: { ! 651: host = scsi_register(tmpt, sizeof(struct isp1020_hostdata)); ! 652: hostdata = (struct isp1020_hostdata *) host->hostdata; ! 653: ! 654: memset(hostdata, 0, sizeof(struct isp1020_hostdata)); ! 655: hostdata->bus = bus; ! 656: hostdata->device_fn = device_fn; ! 657: ! 658: if (isp1020_init(host) || isp1020_reset_hardware(host) ! 659: #if USE_NVRAM_DEFAULTS ! 660: || isp1020_get_defaults(host) ! 661: #else ! 662: || isp1020_set_defaults(host) ! 663: #endif /* USE_NVRAM_DEFAULTS */ ! 664: || isp1020_load_parameters(host)) { ! 665: scsi_unregister(host); ! 666: continue; ! 667: } ! 668: ! 669: host->this_id = hostdata->host_param.initiator_scsi_id; ! 670: ! 671: if (request_irq(host->irq, isp1020_intr_handler, SA_INTERRUPT, ! 672: "qlogicisp", NULL)) ! 673: { ! 674: printk("qlogicisp : interrupt %d already in use\n", ! 675: host->irq); ! 676: scsi_unregister(host); ! 677: continue; ! 678: } ! 679: ! 680: if (check_region(host->io_port, 0xff)) { ! 681: printk("qlogicisp : i/o region 0x%04x-0x%04x already " ! 682: "in use\n", ! 683: host->io_port, host->io_port + 0xff); ! 684: free_irq(host->irq, NULL); ! 685: scsi_unregister(host); ! 686: continue; ! 687: } ! 688: ! 689: request_region(host->io_port, 0xff, "qlogicisp"); ! 690: irq2host[host->irq] = host; ! 691: ! 692: outw(0x0, host->io_port + PCI_SEMAPHORE); ! 693: outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); ! 694: isp1020_enable_irqs(host); ! 695: ! 696: hosts++; ! 697: } ! 698: ! 699: LEAVE("isp1020_detect"); ! 700: ! 701: return hosts; ! 702: } ! 703: ! 704: ! 705: int isp1020_release(struct Scsi_Host *host) ! 706: { ! 707: struct isp1020_hostdata *hostdata; ! 708: ! 709: ENTER("isp1020_release"); ! 710: ! 711: hostdata = (struct isp1020_hostdata *) host->hostdata; ! 712: ! 713: outw(0x0, host->io_port + PCI_INTF_CTL); ! 714: free_irq(host->irq, NULL); ! 715: ! 716: release_region(host->io_port, 0xff); ! 717: ! 718: LEAVE("isp1020_release"); ! 719: ! 720: return 0; ! 721: } ! 722: ! 723: ! 724: const char *isp1020_info(struct Scsi_Host *host) ! 725: { ! 726: static char buf[80]; ! 727: struct isp1020_hostdata *hostdata; ! 728: ! 729: ENTER("isp1020_info"); ! 730: ! 731: hostdata = (struct isp1020_hostdata *) host->hostdata; ! 732: sprintf(buf, ! 733: "QLogic ISP1020 SCSI on PCI bus %d device %d irq %d base 0x%x", ! 734: hostdata->bus, (hostdata->device_fn & 0xf8) >> 3, host->irq, ! 735: host->io_port); ! 736: ! 737: LEAVE("isp1020_info"); ! 738: ! 739: return buf; ! 740: } ! 741: ! 742: ! 743: /* ! 744: * The middle SCSI layer ensures that queuecommand never gets invoked ! 745: * concurrently with itself or the interrupt handler (though the ! 746: * interrupt handler may call this routine as part of ! 747: * request-completion handling). ! 748: */ ! 749: int isp1020_queuecommand(Scsi_Cmnd *Cmnd, void (*done)(Scsi_Cmnd *)) ! 750: { ! 751: int i, sg_count, n, num_free; ! 752: u_int in_ptr, out_ptr; ! 753: struct dataseg * ds; ! 754: struct scatterlist *sg; ! 755: struct Command_Entry *cmd; ! 756: struct Continuation_Entry *cont; ! 757: struct Scsi_Host *host; ! 758: struct isp1020_hostdata *hostdata; ! 759: ! 760: ENTER("isp1020_queuecommand"); ! 761: ! 762: host = Cmnd->host; ! 763: hostdata = (struct isp1020_hostdata *) host->hostdata; ! 764: Cmnd->scsi_done = done; ! 765: ! 766: DEBUG(isp1020_print_scsi_cmd(Cmnd)); ! 767: ! 768: out_ptr = inw(host->io_port + MBOX4); ! 769: in_ptr = hostdata->req_in_ptr; ! 770: ! 771: DEBUG(printk("qlogicisp : request queue depth %d\n", ! 772: REQ_QUEUE_DEPTH(in_ptr, out_ptr))); ! 773: ! 774: cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0]; ! 775: in_ptr = (in_ptr + 1) & QLOGICISP_REQ_QUEUE_LEN; ! 776: if (in_ptr == out_ptr) { ! 777: printk("qlogicisp : request queue overflow\n"); ! 778: return 1; ! 779: } ! 780: ! 781: if (hostdata->send_marker) { ! 782: struct Marker_Entry *marker; ! 783: ! 784: TRACE("queue marker", in_ptr, 0); ! 785: ! 786: DEBUG(printk("qlogicisp : adding marker entry\n")); ! 787: marker = (struct Marker_Entry *) cmd; ! 788: memset(marker, 0, sizeof(struct Marker_Entry)); ! 789: ! 790: marker->hdr.entry_type = ENTRY_MARKER; ! 791: marker->hdr.entry_cnt = 1; ! 792: marker->modifier = SYNC_ALL; ! 793: ! 794: hostdata->send_marker = 0; ! 795: ! 796: if (((in_ptr + 1) & QLOGICISP_REQ_QUEUE_LEN) == out_ptr) { ! 797: outw(in_ptr, host->io_port + MBOX4); ! 798: hostdata->req_in_ptr = in_ptr; ! 799: printk("qlogicisp : request queue overflow\n"); ! 800: return 1; ! 801: } ! 802: cmd = (struct Command_Entry *) &hostdata->req[in_ptr][0]; ! 803: in_ptr = (in_ptr + 1) & QLOGICISP_REQ_QUEUE_LEN; ! 804: } ! 805: ! 806: TRACE("queue command", in_ptr, Cmnd); ! 807: ! 808: memset(cmd, 0, sizeof(struct Command_Entry)); ! 809: ! 810: cmd->hdr.entry_type = ENTRY_COMMAND; ! 811: cmd->hdr.entry_cnt = 1; ! 812: ! 813: cmd->handle = (u_int) virt_to_bus(Cmnd); ! 814: cmd->target_lun = Cmnd->lun; ! 815: cmd->target_id = Cmnd->target; ! 816: cmd->cdb_length = Cmnd->cmd_len; ! 817: cmd->control_flags = CFLAG_READ | CFLAG_WRITE; ! 818: cmd->time_out = 30; ! 819: ! 820: memcpy(cmd->cdb, Cmnd->cmnd, Cmnd->cmd_len); ! 821: ! 822: if (Cmnd->use_sg) { ! 823: cmd->segment_cnt = sg_count = Cmnd->use_sg; ! 824: sg = (struct scatterlist *) Cmnd->request_buffer; ! 825: ds = cmd->dataseg; ! 826: ! 827: /* fill in first four sg entries: */ ! 828: n = sg_count; ! 829: if (n > 4) ! 830: n = 4; ! 831: for (i = 0; i < n; i++) { ! 832: ds[i].d_base = (u_int) virt_to_bus(sg->address); ! 833: ds[i].d_count = sg->length; ! 834: ++sg; ! 835: } ! 836: sg_count -= 4; ! 837: ! 838: while (sg_count > 0) { ! 839: ++cmd->hdr.entry_cnt; ! 840: cont = (struct Continuation_Entry *) ! 841: &hostdata->req[in_ptr][0]; ! 842: in_ptr = (in_ptr + 1) & QLOGICISP_REQ_QUEUE_LEN; ! 843: if (in_ptr == out_ptr) { ! 844: printk("isp1020: unexpected request queue " ! 845: "overflow\n"); ! 846: return 1; ! 847: } ! 848: TRACE("queue continuation", in_ptr, 0); ! 849: cont->hdr.entry_type = ENTRY_CONTINUATION; ! 850: cont->hdr.entry_cnt = 0; ! 851: cont->hdr.sys_def_1 = 0; ! 852: cont->hdr.flags = 0; ! 853: cont->reserved = 0; ! 854: ds = cont->dataseg; ! 855: n = sg_count; ! 856: if (n > 7) ! 857: n = 7; ! 858: for (i = 0; i < n; ++i) { ! 859: ds[i].d_base = (u_int)virt_to_bus(sg->address); ! 860: ds[i].d_count = sg->length; ! 861: ++sg; ! 862: } ! 863: sg_count -= n; ! 864: } ! 865: } else { ! 866: cmd->dataseg[0].d_base = ! 867: (u_int) virt_to_bus(Cmnd->request_buffer); ! 868: cmd->dataseg[0].d_count = ! 869: (u_int) Cmnd->request_bufflen; ! 870: cmd->segment_cnt = 1; ! 871: } ! 872: ! 873: outw(in_ptr, host->io_port + MBOX4); ! 874: hostdata->req_in_ptr = in_ptr; ! 875: ! 876: num_free = QLOGICISP_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr); ! 877: host->can_queue = host->host_busy + num_free; ! 878: host->sg_tablesize = QLOGICISP_MAX_SG(num_free); ! 879: ! 880: LEAVE("isp1020_queuecommand"); ! 881: ! 882: return 0; ! 883: } ! 884: ! 885: ! 886: #define ASYNC_EVENT_INTERRUPT 0x01 ! 887: ! 888: void isp1020_intr_handler(int irq, void *dev_id, struct pt_regs *regs) ! 889: { ! 890: Scsi_Cmnd *Cmnd; ! 891: struct Status_Entry *sts; ! 892: struct Scsi_Host *host; ! 893: struct isp1020_hostdata *hostdata; ! 894: u_int in_ptr, out_ptr; ! 895: u_short status; ! 896: ! 897: ENTER_INTR("isp1020_intr_handler"); ! 898: ! 899: host = irq2host[irq]; ! 900: if (!host) { ! 901: printk("qlogicisp : unexpected interrupt on line %d\n", irq); ! 902: return; ! 903: } ! 904: hostdata = (struct isp1020_hostdata *) host->hostdata; ! 905: ! 906: DEBUG_INTR(printk("qlogicisp : interrupt on line %d\n", irq)); ! 907: ! 908: if (!(inw(host->io_port + PCI_INTF_STS) & 0x04)) { ! 909: /* spurious interrupts can happen legally */ ! 910: DEBUG_INTR(printk("qlogicisp: got spurious interrupt\n")); ! 911: return; ! 912: } ! 913: in_ptr = inw(host->io_port + MBOX5); ! 914: outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); ! 915: ! 916: if ((inw(host->io_port + PCI_SEMAPHORE) & ASYNC_EVENT_INTERRUPT)) { ! 917: status = inw(host->io_port + MBOX0); ! 918: ! 919: DEBUG_INTR(printk("qlogicisp : mbox completion status: %x\n", ! 920: status)); ! 921: ! 922: switch (status) { ! 923: case ASYNC_SCSI_BUS_RESET: ! 924: case EXECUTION_TIMEOUT_RESET: ! 925: hostdata->send_marker = 1; ! 926: break; ! 927: case INVALID_COMMAND: ! 928: case HOST_INTERFACE_ERROR: ! 929: case COMMAND_ERROR: ! 930: case COMMAND_PARAM_ERROR: ! 931: printk("qlogicisp : bad mailbox return status\n"); ! 932: break; ! 933: } ! 934: outw(0x0, host->io_port + PCI_SEMAPHORE); ! 935: } ! 936: out_ptr = hostdata->res_out_ptr; ! 937: ! 938: DEBUG_INTR(printk("qlogicisp : response queue update\n")); ! 939: DEBUG_INTR(printk("qlogicisp : response queue depth %d\n", ! 940: QUEUE_DEPTH(in_ptr, out_ptr))); ! 941: ! 942: while (out_ptr != in_ptr) { ! 943: sts = (struct Status_Entry *) &hostdata->res[out_ptr][0]; ! 944: out_ptr = (out_ptr + 1) & RES_QUEUE_LEN; ! 945: ! 946: Cmnd = (Scsi_Cmnd *) bus_to_virt(sts->handle); ! 947: ! 948: TRACE("done", out_ptr, Cmnd); ! 949: ! 950: if (sts->completion_status == CS_RESET_OCCURRED ! 951: || sts->completion_status == CS_ABORTED ! 952: || (sts->status_flags & STF_BUS_RESET)) ! 953: hostdata->send_marker = 1; ! 954: ! 955: if (sts->state_flags & SF_GOT_SENSE) ! 956: memcpy(Cmnd->sense_buffer, sts->req_sense_data, ! 957: sizeof(Cmnd->sense_buffer)); ! 958: ! 959: DEBUG_INTR(isp1020_print_status_entry(sts)); ! 960: ! 961: if (sts->hdr.entry_type == ENTRY_STATUS) ! 962: Cmnd->result = isp1020_return_status(sts); ! 963: else ! 964: Cmnd->result = DID_ERROR << 16; ! 965: ! 966: outw(out_ptr, host->io_port + MBOX5); ! 967: (*Cmnd->scsi_done)(Cmnd); ! 968: } ! 969: hostdata->res_out_ptr = out_ptr; ! 970: ! 971: LEAVE_INTR("isp1020_intr_handler"); ! 972: } ! 973: ! 974: ! 975: static int isp1020_return_status(struct Status_Entry *sts) ! 976: { ! 977: int host_status = DID_ERROR; ! 978: #if DEBUG_ISP1020_INTR ! 979: static char *reason[] = { ! 980: "DID_OK", ! 981: "DID_NO_CONNECT", ! 982: "DID_BUS_BUSY", ! 983: "DID_TIME_OUT", ! 984: "DID_BAD_TARGET", ! 985: "DID_ABORT", ! 986: "DID_PARITY", ! 987: "DID_ERROR", ! 988: "DID_RESET", ! 989: "DID_BAD_INTR" ! 990: }; ! 991: #endif /* DEBUG_ISP1020_INTR */ ! 992: ! 993: ENTER("isp1020_return_status"); ! 994: ! 995: DEBUG(printk("qlogicisp : completion status = 0x%04x\n", ! 996: sts->completion_status)); ! 997: ! 998: switch(sts->completion_status) { ! 999: case CS_COMPLETE: ! 1000: host_status = DID_OK; ! 1001: break; ! 1002: case CS_INCOMPLETE: ! 1003: if (!(sts->state_flags & SF_GOT_BUS)) ! 1004: host_status = DID_NO_CONNECT; ! 1005: else if (!(sts->state_flags & SF_GOT_TARGET)) ! 1006: host_status = DID_BAD_TARGET; ! 1007: else if (!(sts->state_flags & SF_SENT_CDB)) ! 1008: host_status = DID_ERROR; ! 1009: else if (!(sts->state_flags & SF_TRANSFERRED_DATA)) ! 1010: host_status = DID_ERROR; ! 1011: else if (!(sts->state_flags & SF_GOT_STATUS)) ! 1012: host_status = DID_ERROR; ! 1013: else if (!(sts->state_flags & SF_GOT_SENSE)) ! 1014: host_status = DID_ERROR; ! 1015: break; ! 1016: case CS_DMA_ERROR: ! 1017: case CS_TRANSPORT_ERROR: ! 1018: host_status = DID_ERROR; ! 1019: break; ! 1020: case CS_RESET_OCCURRED: ! 1021: host_status = DID_RESET; ! 1022: break; ! 1023: case CS_ABORTED: ! 1024: host_status = DID_ABORT; ! 1025: break; ! 1026: case CS_TIMEOUT: ! 1027: host_status = DID_TIME_OUT; ! 1028: break; ! 1029: case CS_DATA_OVERRUN: ! 1030: case CS_COMMAND_OVERRUN: ! 1031: case CS_STATUS_OVERRUN: ! 1032: case CS_BAD_MESSAGE: ! 1033: case CS_NO_MESSAGE_OUT: ! 1034: case CS_EXT_ID_FAILED: ! 1035: case CS_IDE_MSG_FAILED: ! 1036: case CS_ABORT_MSG_FAILED: ! 1037: case CS_NOP_MSG_FAILED: ! 1038: case CS_PARITY_ERROR_MSG_FAILED: ! 1039: case CS_DEVICE_RESET_MSG_FAILED: ! 1040: case CS_ID_MSG_FAILED: ! 1041: case CS_UNEXP_BUS_FREE: ! 1042: case CS_INVALID_ENTRY_TYPE: ! 1043: case CS_DEVICE_QUEUE_FULL: ! 1044: case CS_SCSI_PHASE_SKIPPED: ! 1045: case CS_ARS_FAILED: ! 1046: host_status = DID_ERROR; ! 1047: break; ! 1048: case CS_DATA_UNDERRUN: ! 1049: host_status = DID_OK; ! 1050: break; ! 1051: default: ! 1052: printk("qlogicisp : unknown completion status 0x%04x\n", ! 1053: sts->completion_status); ! 1054: host_status = DID_ERROR; ! 1055: break; ! 1056: } ! 1057: ! 1058: DEBUG_INTR(printk("qlogicisp : host status (%s) scsi status %x\n", ! 1059: reason[host_status], sts->scsi_status)); ! 1060: ! 1061: LEAVE("isp1020_return_status"); ! 1062: ! 1063: return (sts->scsi_status & STATUS_MASK) | (host_status << 16); ! 1064: } ! 1065: ! 1066: ! 1067: int isp1020_abort(Scsi_Cmnd *Cmnd) ! 1068: { ! 1069: u_short param[6]; ! 1070: struct Scsi_Host *host; ! 1071: struct isp1020_hostdata *hostdata; ! 1072: int return_status = SCSI_ABORT_SUCCESS; ! 1073: u_int cmdaddr = virt_to_bus(Cmnd); ! 1074: ! 1075: ENTER("isp1020_abort"); ! 1076: ! 1077: host = Cmnd->host; ! 1078: hostdata = (struct isp1020_hostdata *) host->hostdata; ! 1079: ! 1080: isp1020_disable_irqs(host); ! 1081: ! 1082: param[0] = MBOX_ABORT; ! 1083: param[1] = (((u_short) Cmnd->target) << 8) | Cmnd->lun; ! 1084: param[2] = cmdaddr >> 16; ! 1085: param[3] = cmdaddr & 0xffff; ! 1086: ! 1087: isp1020_mbox_command(host, param); ! 1088: ! 1089: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1090: printk("qlogicisp : scsi abort failure: %x\n", param[0]); ! 1091: return_status = SCSI_ABORT_ERROR; ! 1092: } ! 1093: ! 1094: isp1020_enable_irqs(host); ! 1095: ! 1096: LEAVE("isp1020_abort"); ! 1097: ! 1098: return return_status; ! 1099: } ! 1100: ! 1101: ! 1102: int isp1020_reset(Scsi_Cmnd *Cmnd, unsigned int reset_flags) ! 1103: { ! 1104: u_short param[6]; ! 1105: struct Scsi_Host *host; ! 1106: struct isp1020_hostdata *hostdata; ! 1107: int return_status = SCSI_RESET_SUCCESS; ! 1108: ! 1109: ENTER("isp1020_reset"); ! 1110: ! 1111: host = Cmnd->host; ! 1112: hostdata = (struct isp1020_hostdata *) host->hostdata; ! 1113: ! 1114: param[0] = MBOX_BUS_RESET; ! 1115: param[1] = hostdata->host_param.bus_reset_delay; ! 1116: ! 1117: isp1020_disable_irqs(host); ! 1118: ! 1119: isp1020_mbox_command(host, param); ! 1120: ! 1121: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1122: printk("qlogicisp : scsi bus reset failure: %x\n", param[0]); ! 1123: return_status = SCSI_RESET_ERROR; ! 1124: } ! 1125: ! 1126: isp1020_enable_irqs(host); ! 1127: ! 1128: LEAVE("isp1020_reset"); ! 1129: ! 1130: return return_status;; ! 1131: } ! 1132: ! 1133: ! 1134: int isp1020_biosparam(Disk *disk, kdev_t n, int ip[]) ! 1135: { ! 1136: int size = disk->capacity; ! 1137: ! 1138: ENTER("isp1020_biosparam"); ! 1139: ! 1140: ip[0] = 64; ! 1141: ip[1] = 32; ! 1142: ip[2] = size >> 11; ! 1143: if (ip[2] > 1024) { ! 1144: ip[0] = 255; ! 1145: ip[1] = 63; ! 1146: ip[2] = size / (ip[0] * ip[1]); ! 1147: if (ip[2] > 1023) ! 1148: ip[2] = 1023; ! 1149: } ! 1150: ! 1151: LEAVE("isp1020_biosparam"); ! 1152: ! 1153: return 0; ! 1154: } ! 1155: ! 1156: ! 1157: static int isp1020_reset_hardware(struct Scsi_Host *host) ! 1158: { ! 1159: u_short param[6]; ! 1160: int loop_count; ! 1161: ! 1162: ENTER("isp1020_reset_hardware"); ! 1163: ! 1164: outw(ISP_RESET, host->io_port + PCI_INTF_CTL); ! 1165: outw(HCCR_RESET, host->io_port + HOST_HCCR); ! 1166: outw(HCCR_RELEASE, host->io_port + HOST_HCCR); ! 1167: outw(HCCR_BIOS_DISABLE, host->io_port + HOST_HCCR); ! 1168: ! 1169: loop_count = DEFAULT_LOOP_COUNT; ! 1170: while (--loop_count && inw(host->io_port + HOST_HCCR) == RISC_BUSY) ! 1171: barrier(); ! 1172: if (!loop_count) ! 1173: printk("qlogicisp: reset_hardware loop timeout\n"); ! 1174: ! 1175: outw(0, host->io_port + ISP_CFG1); ! 1176: ! 1177: #if DEBUG_ISP1020 ! 1178: printk("qlogicisp : mbox 0 0x%04x \n", inw(host->io_port + MBOX0)); ! 1179: printk("qlogicisp : mbox 1 0x%04x \n", inw(host->io_port + MBOX1)); ! 1180: printk("qlogicisp : mbox 2 0x%04x \n", inw(host->io_port + MBOX2)); ! 1181: printk("qlogicisp : mbox 3 0x%04x \n", inw(host->io_port + MBOX3)); ! 1182: printk("qlogicisp : mbox 4 0x%04x \n", inw(host->io_port + MBOX4)); ! 1183: printk("qlogicisp : mbox 5 0x%04x \n", inw(host->io_port + MBOX5)); ! 1184: #endif /* DEBUG_ISP1020 */ ! 1185: ! 1186: DEBUG(printk("qlogicisp : loading risc ram\n")); ! 1187: ! 1188: #if RELOAD_FIRMWARE ! 1189: { ! 1190: int i; ! 1191: for (i = 0; i < risc_code_length01; i++) { ! 1192: param[0] = MBOX_WRITE_RAM_WORD; ! 1193: param[1] = risc_code_addr01 + i; ! 1194: param[2] = risc_code01[i]; ! 1195: ! 1196: isp1020_mbox_command(host, param); ! 1197: ! 1198: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1199: printk("qlogicisp : firmware load failure\n"); ! 1200: return 1; ! 1201: } ! 1202: } ! 1203: } ! 1204: #endif /* RELOAD_FIRMWARE */ ! 1205: ! 1206: DEBUG(printk("qlogicisp : verifying checksum\n")); ! 1207: ! 1208: param[0] = MBOX_VERIFY_CHECKSUM; ! 1209: param[1] = risc_code_addr01; ! 1210: ! 1211: isp1020_mbox_command(host, param); ! 1212: ! 1213: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1214: printk("qlogicisp : ram checksum failure\n"); ! 1215: return 1; ! 1216: } ! 1217: ! 1218: DEBUG(printk("qlogicisp : executing firmware\n")); ! 1219: ! 1220: param[0] = MBOX_EXEC_FIRMWARE; ! 1221: param[1] = risc_code_addr01; ! 1222: ! 1223: isp1020_mbox_command(host, param); ! 1224: ! 1225: param[0] = MBOX_ABOUT_FIRMWARE; ! 1226: ! 1227: isp1020_mbox_command(host, param); ! 1228: ! 1229: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1230: printk("qlogicisp : about firmware failure\n"); ! 1231: return 1; ! 1232: } ! 1233: ! 1234: DEBUG(printk("qlogicisp : firmware major revision %d\n", param[1])); ! 1235: DEBUG(printk("qlogicisp : firmware minor revision %d\n", param[2])); ! 1236: ! 1237: LEAVE("isp1020_reset_hardware"); ! 1238: ! 1239: return 0; ! 1240: } ! 1241: ! 1242: ! 1243: static int isp1020_init(struct Scsi_Host *sh) ! 1244: { ! 1245: u_int io_base; ! 1246: struct isp1020_hostdata *hostdata; ! 1247: u_char bus, device_fn, revision, irq; ! 1248: u_short vendor_id, device_id, command; ! 1249: ! 1250: ENTER("isp1020_init"); ! 1251: ! 1252: hostdata = (struct isp1020_hostdata *) sh->hostdata; ! 1253: bus = hostdata->bus; ! 1254: device_fn = hostdata->device_fn; ! 1255: ! 1256: if (pcibios_read_config_word(bus, device_fn, PCI_VENDOR_ID, &vendor_id) ! 1257: || pcibios_read_config_word(bus, device_fn, ! 1258: PCI_DEVICE_ID, &device_id) ! 1259: || pcibios_read_config_word(bus, device_fn, ! 1260: PCI_COMMAND, &command) ! 1261: || pcibios_read_config_dword(bus, device_fn, ! 1262: PCI_BASE_ADDRESS_0, &io_base) ! 1263: || pcibios_read_config_byte(bus, device_fn, ! 1264: PCI_CLASS_REVISION, &revision) ! 1265: || pcibios_read_config_byte(bus, device_fn, ! 1266: PCI_INTERRUPT_LINE, &irq)) ! 1267: { ! 1268: printk("qlogicisp : error reading PCI configuration\n"); ! 1269: return 1; ! 1270: } ! 1271: ! 1272: if (vendor_id != PCI_VENDOR_ID_QLOGIC) { ! 1273: printk("qlogicisp : 0x%04x is not QLogic vendor ID\n", ! 1274: vendor_id); ! 1275: return 1; ! 1276: } ! 1277: ! 1278: if (device_id != PCI_DEVICE_ID_QLOGIC_ISP1020) { ! 1279: printk("qlogicisp : 0x%04x does not match ISP1020 device id\n", ! 1280: device_id); ! 1281: return 1; ! 1282: } ! 1283: ! 1284: if (command & PCI_COMMAND_IO && (io_base & 3) == 1) ! 1285: io_base &= PCI_BASE_ADDRESS_IO_MASK; ! 1286: else { ! 1287: printk("qlogicisp : i/o mapping is disabled\n"); ! 1288: return 1; ! 1289: } ! 1290: ! 1291: if (!(command & PCI_COMMAND_MASTER)) { ! 1292: printk("qlogicisp : bus mastering is disabled\n"); ! 1293: return 1; ! 1294: } ! 1295: ! 1296: if (revision != ISP1020_REV_ID) ! 1297: printk("qlogicisp : new isp1020 revision ID (%d)\n", revision); ! 1298: ! 1299: if (inw(io_base + PCI_ID_LOW) != PCI_VENDOR_ID_QLOGIC ! 1300: || inw(io_base + PCI_ID_HIGH) != PCI_DEVICE_ID_QLOGIC_ISP1020) ! 1301: { ! 1302: printk("qlogicisp : can't decode i/o address space at 0x%x\n", ! 1303: io_base); ! 1304: return 1; ! 1305: } ! 1306: ! 1307: hostdata->revision = revision; ! 1308: ! 1309: sh->irq = irq; ! 1310: sh->io_port = io_base; ! 1311: ! 1312: LEAVE("isp1020_init"); ! 1313: ! 1314: return 0; ! 1315: } ! 1316: ! 1317: ! 1318: #if USE_NVRAM_DEFAULTS ! 1319: ! 1320: static int isp1020_get_defaults(struct Scsi_Host *host) ! 1321: { ! 1322: int i; ! 1323: u_short value; ! 1324: struct isp1020_hostdata *hostdata = ! 1325: (struct isp1020_hostdata *) host->hostdata; ! 1326: ! 1327: ENTER("isp1020_get_defaults"); ! 1328: ! 1329: if (!isp1020_verify_nvram(host)) { ! 1330: printk("qlogicisp : nvram checksum failure\n"); ! 1331: printk("qlogicisp : attempting to use default parameters\n"); ! 1332: return isp1020_set_defaults(host); ! 1333: } ! 1334: ! 1335: value = isp1020_read_nvram_word(host, 2); ! 1336: hostdata->host_param.fifo_threshold = (value >> 8) & 0x03; ! 1337: hostdata->host_param.host_adapter_enable = (value >> 11) & 0x01; ! 1338: hostdata->host_param.initiator_scsi_id = (value >> 12) & 0x0f; ! 1339: ! 1340: value = isp1020_read_nvram_word(host, 3); ! 1341: hostdata->host_param.bus_reset_delay = value & 0xff; ! 1342: hostdata->host_param.retry_count = value >> 8; ! 1343: ! 1344: value = isp1020_read_nvram_word(host, 4); ! 1345: hostdata->host_param.retry_delay = value & 0xff; ! 1346: hostdata->host_param.async_data_setup_time = (value >> 8) & 0x0f; ! 1347: hostdata->host_param.req_ack_active_negation = (value >> 12) & 0x01; ! 1348: hostdata->host_param.data_line_active_negation = (value >> 13) & 0x01; ! 1349: hostdata->host_param.data_dma_burst_enable = (value >> 14) & 0x01; ! 1350: hostdata->host_param.command_dma_burst_enable = (value >> 15); ! 1351: ! 1352: value = isp1020_read_nvram_word(host, 5); ! 1353: hostdata->host_param.tag_aging = value & 0xff; ! 1354: ! 1355: value = isp1020_read_nvram_word(host, 6); ! 1356: hostdata->host_param.selection_timeout = value & 0xffff; ! 1357: ! 1358: value = isp1020_read_nvram_word(host, 7); ! 1359: hostdata->host_param.max_queue_depth = value & 0xffff; ! 1360: ! 1361: #if DEBUG_ISP1020_SETUP ! 1362: printk("qlogicisp : fifo threshold=%d\n", ! 1363: hostdata->host_param.fifo_threshold); ! 1364: printk("qlogicisp : initiator scsi id=%d\n", ! 1365: hostdata->host_param.initiator_scsi_id); ! 1366: printk("qlogicisp : bus reset delay=%d\n", ! 1367: hostdata->host_param.bus_reset_delay); ! 1368: printk("qlogicisp : retry count=%d\n", ! 1369: hostdata->host_param.retry_count); ! 1370: printk("qlogicisp : retry delay=%d\n", ! 1371: hostdata->host_param.retry_delay); ! 1372: printk("qlogicisp : async data setup time=%d\n", ! 1373: hostdata->host_param.async_data_setup_time); ! 1374: printk("qlogicisp : req/ack active negation=%d\n", ! 1375: hostdata->host_param.req_ack_active_negation); ! 1376: printk("qlogicisp : data line active negation=%d\n", ! 1377: hostdata->host_param.data_line_active_negation); ! 1378: printk("qlogicisp : data DMA burst enable=%d\n", ! 1379: hostdata->host_param.data_dma_burst_enable); ! 1380: printk("qlogicisp : command DMA burst enable=%d\n", ! 1381: hostdata->host_param.command_dma_burst_enable); ! 1382: printk("qlogicisp : tag age limit=%d\n", ! 1383: hostdata->host_param.tag_aging); ! 1384: printk("qlogicisp : selection timeout limit=%d\n", ! 1385: hostdata->host_param.selection_timeout); ! 1386: printk("qlogicisp : max queue depth=%d\n", ! 1387: hostdata->host_param.max_queue_depth); ! 1388: #endif /* DEBUG_ISP1020_SETUP */ ! 1389: ! 1390: for (i = 0; i < MAX_TARGETS; i++) { ! 1391: ! 1392: value = isp1020_read_nvram_word(host, 14 + i * 3); ! 1393: hostdata->dev_param[i].device_flags = value & 0xff; ! 1394: hostdata->dev_param[i].execution_throttle = value >> 8; ! 1395: ! 1396: value = isp1020_read_nvram_word(host, 15 + i * 3); ! 1397: hostdata->dev_param[i].synchronous_period = value & 0xff; ! 1398: hostdata->dev_param[i].synchronous_offset = (value >> 8) & 0x0f; ! 1399: hostdata->dev_param[i].device_enable = (value >> 12) & 0x01; ! 1400: ! 1401: #if DEBUG_ISP1020_SETUP ! 1402: printk("qlogicisp : target 0x%02x\n", i); ! 1403: printk("qlogicisp : device flags=0x%02x\n", ! 1404: hostdata->dev_param[i].device_flags); ! 1405: printk("qlogicisp : execution throttle=%d\n", ! 1406: hostdata->dev_param[i].execution_throttle); ! 1407: printk("qlogicisp : synchronous period=%d\n", ! 1408: hostdata->dev_param[i].synchronous_period); ! 1409: printk("qlogicisp : synchronous offset=%d\n", ! 1410: hostdata->dev_param[i].synchronous_offset); ! 1411: printk("qlogicisp : device enable=%d\n", ! 1412: hostdata->dev_param[i].device_enable); ! 1413: #endif /* DEBUG_ISP1020_SETUP */ ! 1414: } ! 1415: ! 1416: LEAVE("isp1020_get_defaults"); ! 1417: ! 1418: return 0; ! 1419: } ! 1420: ! 1421: ! 1422: #define ISP1020_NVRAM_LEN 0x40 ! 1423: #define ISP1020_NVRAM_SIG1 0x5349 ! 1424: #define ISP1020_NVRAM_SIG2 0x2050 ! 1425: ! 1426: static int isp1020_verify_nvram(struct Scsi_Host *host) ! 1427: { ! 1428: int i; ! 1429: u_short value; ! 1430: u_char checksum = 0; ! 1431: ! 1432: for (i = 0; i < ISP1020_NVRAM_LEN; i++) { ! 1433: value = isp1020_read_nvram_word(host, i); ! 1434: ! 1435: switch (i) { ! 1436: case 0: ! 1437: if (value != ISP1020_NVRAM_SIG1) return 0; ! 1438: break; ! 1439: case 1: ! 1440: if (value != ISP1020_NVRAM_SIG2) return 0; ! 1441: break; ! 1442: case 2: ! 1443: if ((value & 0xff) != 0x02) return 0; ! 1444: break; ! 1445: } ! 1446: checksum += value & 0xff; ! 1447: checksum += value >> 8; ! 1448: } ! 1449: ! 1450: return (checksum == 0); ! 1451: } ! 1452: ! 1453: #define NVRAM_DELAY() udelay(2) /* 2 microsecond delay */ ! 1454: ! 1455: ! 1456: u_short isp1020_read_nvram_word(struct Scsi_Host *host, u_short byte) ! 1457: { ! 1458: int i; ! 1459: u_short value, output, input; ! 1460: ! 1461: byte &= 0x3f; byte |= 0x0180; ! 1462: ! 1463: for (i = 8; i >= 0; i--) { ! 1464: output = ((byte >> i) & 0x1) ? 0x4 : 0x0; ! 1465: outw(output | 0x2, host->io_port + PCI_NVRAM); NVRAM_DELAY(); ! 1466: outw(output | 0x3, host->io_port + PCI_NVRAM); NVRAM_DELAY(); ! 1467: outw(output | 0x2, host->io_port + PCI_NVRAM); NVRAM_DELAY(); ! 1468: } ! 1469: ! 1470: for (i = 0xf, value = 0; i >= 0; i--) { ! 1471: value <<= 1; ! 1472: outw(0x3, host->io_port + PCI_NVRAM); NVRAM_DELAY(); ! 1473: input = inw(host->io_port + PCI_NVRAM); NVRAM_DELAY(); ! 1474: outw(0x2, host->io_port + PCI_NVRAM); NVRAM_DELAY(); ! 1475: if (input & 0x8) value |= 1; ! 1476: } ! 1477: ! 1478: outw(0x0, host->io_port + PCI_NVRAM); NVRAM_DELAY(); ! 1479: ! 1480: return value; ! 1481: } ! 1482: ! 1483: #endif /* USE_NVRAM_DEFAULTS */ ! 1484: ! 1485: ! 1486: static int isp1020_set_defaults(struct Scsi_Host *host) ! 1487: { ! 1488: struct isp1020_hostdata *hostdata = ! 1489: (struct isp1020_hostdata *) host->hostdata; ! 1490: int i; ! 1491: ! 1492: ENTER("isp1020_set_defaults"); ! 1493: ! 1494: hostdata->host_param.fifo_threshold = 2; ! 1495: hostdata->host_param.host_adapter_enable = 1; ! 1496: hostdata->host_param.initiator_scsi_id = 7; ! 1497: hostdata->host_param.bus_reset_delay = 3; ! 1498: hostdata->host_param.retry_count = 0; ! 1499: hostdata->host_param.retry_delay = 1; ! 1500: hostdata->host_param.async_data_setup_time = 6; ! 1501: hostdata->host_param.req_ack_active_negation = 1; ! 1502: hostdata->host_param.data_line_active_negation = 1; ! 1503: hostdata->host_param.data_dma_burst_enable = 1; ! 1504: hostdata->host_param.command_dma_burst_enable = 1; ! 1505: hostdata->host_param.tag_aging = 8; ! 1506: hostdata->host_param.selection_timeout = 250; ! 1507: hostdata->host_param.max_queue_depth = 256; ! 1508: ! 1509: for (i = 0; i < MAX_TARGETS; i++) { ! 1510: hostdata->dev_param[i].device_flags = 0xfd; ! 1511: hostdata->dev_param[i].execution_throttle = 16; ! 1512: hostdata->dev_param[i].synchronous_period = 25; ! 1513: hostdata->dev_param[i].synchronous_offset = 12; ! 1514: hostdata->dev_param[i].device_enable = 1; ! 1515: } ! 1516: ! 1517: LEAVE("isp1020_set_defaults"); ! 1518: ! 1519: return 0; ! 1520: } ! 1521: ! 1522: ! 1523: static int isp1020_load_parameters(struct Scsi_Host *host) ! 1524: { ! 1525: int i, k; ! 1526: u_int queue_addr; ! 1527: u_short param[6]; ! 1528: u_short isp_cfg1; ! 1529: unsigned long flags; ! 1530: struct isp1020_hostdata *hostdata = ! 1531: (struct isp1020_hostdata *) host->hostdata; ! 1532: ! 1533: ENTER("isp1020_load_parameters"); ! 1534: ! 1535: save_flags(flags); ! 1536: cli(); ! 1537: ! 1538: outw(hostdata->host_param.fifo_threshold, host->io_port + ISP_CFG1); ! 1539: ! 1540: param[0] = MBOX_SET_INIT_SCSI_ID; ! 1541: param[1] = hostdata->host_param.initiator_scsi_id; ! 1542: ! 1543: isp1020_mbox_command(host, param); ! 1544: ! 1545: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1546: restore_flags(flags); ! 1547: printk("qlogicisp : set initiator id failure\n"); ! 1548: return 1; ! 1549: } ! 1550: ! 1551: param[0] = MBOX_SET_RETRY_COUNT; ! 1552: param[1] = hostdata->host_param.retry_count; ! 1553: param[2] = hostdata->host_param.retry_delay; ! 1554: ! 1555: isp1020_mbox_command(host, param); ! 1556: ! 1557: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1558: restore_flags(flags); ! 1559: printk("qlogicisp : set retry count failure\n"); ! 1560: return 1; ! 1561: } ! 1562: ! 1563: param[0] = MBOX_SET_ASYNC_DATA_SETUP_TIME; ! 1564: param[1] = hostdata->host_param.async_data_setup_time; ! 1565: ! 1566: isp1020_mbox_command(host, param); ! 1567: ! 1568: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1569: restore_flags(flags); ! 1570: printk("qlogicisp : async data setup time failure\n"); ! 1571: return 1; ! 1572: } ! 1573: ! 1574: param[0] = MBOX_SET_ACTIVE_NEG_STATE; ! 1575: param[1] = (hostdata->host_param.req_ack_active_negation << 4) ! 1576: | (hostdata->host_param.data_line_active_negation << 5); ! 1577: ! 1578: isp1020_mbox_command(host, param); ! 1579: ! 1580: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1581: restore_flags(flags); ! 1582: printk("qlogicisp : set active negation state failure\n"); ! 1583: return 1; ! 1584: } ! 1585: ! 1586: param[0] = MBOX_SET_PCI_CONTROL_PARAMS; ! 1587: param[1] = hostdata->host_param.data_dma_burst_enable << 1; ! 1588: param[2] = hostdata->host_param.command_dma_burst_enable << 1; ! 1589: ! 1590: isp1020_mbox_command(host, param); ! 1591: ! 1592: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1593: restore_flags(flags); ! 1594: printk("qlogicisp : set pci control parameter failure\n"); ! 1595: return 1; ! 1596: } ! 1597: ! 1598: isp_cfg1 = inw(host->io_port + ISP_CFG1); ! 1599: ! 1600: if (hostdata->host_param.data_dma_burst_enable ! 1601: || hostdata->host_param.command_dma_burst_enable) ! 1602: isp_cfg1 |= 0x0004; ! 1603: else ! 1604: isp_cfg1 &= 0xfffb; ! 1605: ! 1606: outw(isp_cfg1, host->io_port + ISP_CFG1); ! 1607: ! 1608: param[0] = MBOX_SET_TAG_AGE_LIMIT; ! 1609: param[1] = hostdata->host_param.tag_aging; ! 1610: ! 1611: isp1020_mbox_command(host, param); ! 1612: ! 1613: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1614: restore_flags(flags); ! 1615: printk("qlogicisp : set tag age limit failure\n"); ! 1616: return 1; ! 1617: } ! 1618: ! 1619: param[0] = MBOX_SET_SELECT_TIMEOUT; ! 1620: param[1] = hostdata->host_param.selection_timeout; ! 1621: ! 1622: isp1020_mbox_command(host, param); ! 1623: ! 1624: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1625: restore_flags(flags); ! 1626: printk("qlogicisp : set selection timeout failure\n"); ! 1627: return 1; ! 1628: } ! 1629: ! 1630: for (i = 0; i < MAX_TARGETS; i++) { ! 1631: ! 1632: if (!hostdata->dev_param[i].device_enable) ! 1633: continue; ! 1634: ! 1635: param[0] = MBOX_SET_TARGET_PARAMS; ! 1636: param[1] = i << 8; ! 1637: param[2] = hostdata->dev_param[i].device_flags << 8; ! 1638: param[3] = (hostdata->dev_param[i].synchronous_offset << 8) ! 1639: | hostdata->dev_param[i].synchronous_period; ! 1640: ! 1641: isp1020_mbox_command(host, param); ! 1642: ! 1643: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1644: restore_flags(flags); ! 1645: printk("qlogicisp : set target parameter failure\n"); ! 1646: return 1; ! 1647: } ! 1648: ! 1649: for (k = 0; k < MAX_LUNS; k++) { ! 1650: ! 1651: param[0] = MBOX_SET_DEV_QUEUE_PARAMS; ! 1652: param[1] = (i << 8) | k; ! 1653: param[2] = hostdata->host_param.max_queue_depth; ! 1654: param[3] = hostdata->dev_param[i].execution_throttle; ! 1655: ! 1656: isp1020_mbox_command(host, param); ! 1657: ! 1658: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1659: restore_flags(flags); ! 1660: printk("qlogicisp : set device queue " ! 1661: "parameter failure\n"); ! 1662: return 1; ! 1663: } ! 1664: } ! 1665: } ! 1666: ! 1667: queue_addr = (u_int) virt_to_bus(&hostdata->res[0][0]); ! 1668: ! 1669: param[0] = MBOX_INIT_RES_QUEUE; ! 1670: param[1] = RES_QUEUE_LEN + 1; ! 1671: param[2] = (u_short) (queue_addr >> 16); ! 1672: param[3] = (u_short) (queue_addr & 0xffff); ! 1673: param[4] = 0; ! 1674: param[5] = 0; ! 1675: ! 1676: isp1020_mbox_command(host, param); ! 1677: ! 1678: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1679: restore_flags(flags); ! 1680: printk("qlogicisp : set response queue failure\n"); ! 1681: return 1; ! 1682: } ! 1683: ! 1684: queue_addr = (u_int) virt_to_bus(&hostdata->req[0][0]); ! 1685: ! 1686: param[0] = MBOX_INIT_REQ_QUEUE; ! 1687: param[1] = QLOGICISP_REQ_QUEUE_LEN + 1; ! 1688: param[2] = (u_short) (queue_addr >> 16); ! 1689: param[3] = (u_short) (queue_addr & 0xffff); ! 1690: param[4] = 0; ! 1691: ! 1692: isp1020_mbox_command(host, param); ! 1693: ! 1694: if (param[0] != MBOX_COMMAND_COMPLETE) { ! 1695: restore_flags(flags); ! 1696: printk("qlogicisp : set request queue failure\n"); ! 1697: return 1; ! 1698: } ! 1699: ! 1700: restore_flags(flags); ! 1701: ! 1702: LEAVE("isp1020_load_parameters"); ! 1703: ! 1704: return 0; ! 1705: } ! 1706: ! 1707: ! 1708: /* ! 1709: * currently, this is only called during initialization or abort/reset, ! 1710: * at which times interrupts are disabled, so polling is OK, I guess... ! 1711: */ ! 1712: static int isp1020_mbox_command(struct Scsi_Host *host, u_short param[]) ! 1713: { ! 1714: int loop_count; ! 1715: ! 1716: if (mbox_param[param[0]] == 0) ! 1717: return 1; ! 1718: ! 1719: loop_count = DEFAULT_LOOP_COUNT; ! 1720: while (--loop_count && inw(host->io_port + HOST_HCCR) & 0x0080) ! 1721: barrier(); ! 1722: if (!loop_count) ! 1723: printk("qlogicisp: mbox_command loop timeout #1\n"); ! 1724: ! 1725: switch(mbox_param[param[0]] >> 4) { ! 1726: case 6: outw(param[5], host->io_port + MBOX5); ! 1727: case 5: outw(param[4], host->io_port + MBOX4); ! 1728: case 4: outw(param[3], host->io_port + MBOX3); ! 1729: case 3: outw(param[2], host->io_port + MBOX2); ! 1730: case 2: outw(param[1], host->io_port + MBOX1); ! 1731: case 1: outw(param[0], host->io_port + MBOX0); ! 1732: } ! 1733: ! 1734: outw(0x0, host->io_port + PCI_SEMAPHORE); ! 1735: outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); ! 1736: outw(HCCR_SET_HOST_INTR, host->io_port + HOST_HCCR); ! 1737: ! 1738: loop_count = DEFAULT_LOOP_COUNT; ! 1739: while (--loop_count && !(inw(host->io_port + PCI_INTF_STS) & 0x04)) ! 1740: barrier(); ! 1741: if (!loop_count) ! 1742: printk("qlogicisp: mbox_command loop timeout #2\n"); ! 1743: ! 1744: loop_count = DEFAULT_LOOP_COUNT; ! 1745: while (--loop_count && inw(host->io_port + MBOX0) == 0x04) ! 1746: barrier(); ! 1747: if (!loop_count) ! 1748: printk("qlogicisp: mbox_command loop timeout #3\n"); ! 1749: ! 1750: switch(mbox_param[param[0]] & 0xf) { ! 1751: case 6: param[5] = inw(host->io_port + MBOX5); ! 1752: case 5: param[4] = inw(host->io_port + MBOX4); ! 1753: case 4: param[3] = inw(host->io_port + MBOX3); ! 1754: case 3: param[2] = inw(host->io_port + MBOX2); ! 1755: case 2: param[1] = inw(host->io_port + MBOX1); ! 1756: case 1: param[0] = inw(host->io_port + MBOX0); ! 1757: } ! 1758: ! 1759: outw(0x0, host->io_port + PCI_SEMAPHORE); ! 1760: outw(HCCR_CLEAR_RISC_INTR, host->io_port + HOST_HCCR); ! 1761: ! 1762: return 0; ! 1763: } ! 1764: ! 1765: ! 1766: #if DEBUG_ISP1020_INTR ! 1767: ! 1768: void isp1020_print_status_entry(struct Status_Entry *status) ! 1769: { ! 1770: int i; ! 1771: ! 1772: printk("qlogicisp : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n", ! 1773: status->hdr.entry_cnt, status->hdr.entry_type, status->hdr.flags); ! 1774: printk("qlogicisp : scsi status = 0x%04x, completion status = 0x%04x\n", ! 1775: status->scsi_status, status->completion_status); ! 1776: printk("qlogicisp : state flags = 0x%04x, status flags = 0x%04x\n", ! 1777: status->state_flags, status->status_flags); ! 1778: printk("qlogicisp : time = 0x%04x, request sense length = 0x%04x\n", ! 1779: status->time, status->req_sense_len); ! 1780: printk("qlogicisp : residual transfer length = 0x%08x\n", status->residual); ! 1781: ! 1782: for (i = 0; i < status->req_sense_len; i++) ! 1783: printk("qlogicisp : sense data = 0x%02x\n", status->req_sense_data[i]); ! 1784: } ! 1785: ! 1786: #endif /* DEBUG_ISP1020_INTR */ ! 1787: ! 1788: ! 1789: #if DEBUG_ISP1020 ! 1790: ! 1791: void isp1020_print_scsi_cmd(Scsi_Cmnd *cmd) ! 1792: { ! 1793: int i; ! 1794: ! 1795: printk("qlogicisp : target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n", ! 1796: cmd->target, cmd->lun, cmd->cmd_len); ! 1797: printk("qlogicisp : command = "); ! 1798: for (i = 0; i < cmd->cmd_len; i++) ! 1799: printk("0x%02x ", cmd->cmnd[i]); ! 1800: printk("\n"); ! 1801: } ! 1802: ! 1803: #endif /* DEBUG_ISP1020 */ ! 1804: ! 1805: ! 1806: #ifdef MODULE ! 1807: Scsi_Host_Template driver_template = QLOGICISP; ! 1808: ! 1809: #include "scsi_module.c" ! 1810: #endif /* MODULE */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.