Annotation of Gnu-Mach/linux/src/drivers/scsi/qlogicisp.c, revision 1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.