blob: 54d0776edde4f66b6de826a71d4dc8648ce2b5df [file] [log] [blame]
/******************************************************************************
* QLOGIC LINUX SOFTWARE
*
* QLogic QLA1280 (Ultra2) and QLA12160 (Ultra3) SCSI driver
* Copyright (C) 2000 Qlogic Corporation (www.qlogic.com)
* Copyright (C) 2001-2002 Jes Sorensen, Wild Open Source Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
******************************************************************************/
#define QLA1280_VERSION "3.23.19 Beta"
/******************************************************************************
Revision History:
Rev 3.23.19 Beta April 11, 2002, Linus Torvalds
- Do qla1280_pci_config() before calling request_irq() and
request_region()
- Use pci_dma_hi32() to handle upper word of DMA addresses instead
of large shifts
- Hand correct arguments to free_irq() in case of failure
Rev 3.23.18 Beta April 11, 2002, Jes Sorensen
- Run source through Lindent and clean up the output
Rev 3.23.17 Beta April 11, 2002, Jes Sorensen
- Update SCSI firmware to qla1280 v8.15.00 and qla12160 v10.04.32
Rev 3.23.16 Beta March 19, 2002, Jes Sorensen
- Rely on mailbox commands generating interrupts - do not
run qla1280_isr() from ql1280_mailbox_command()
- Remove device_reg_t
- Integrate ql12160_set_target_parameters() with 1280 version
- Make qla1280_setup() non static
- Do not call qla1280_check_for_dead_scsi_bus() on every I/O request
sent to the card - this command pauses the firmare!!!
Rev 3.23.15 Beta March 19, 2002, Jes Sorensen
- Clean up qla1280.h - remove obsolete QL_DEBUG_LEVEL_x definitions
- Remove a pile of pointless and confusing (srb_t **) and
(scsi_lu_t *) typecasts
- Explicit mark that we do not use the new error handling (for now)
- Remove scsi_qla_host_t and use 'struct' instead
- Remove in_abort, watchdog_enabled, dpc, dpc_sched, bios_enabled,
pci_64bit_slot flags which weren't used for anything anyway
- Grab host->host_lock while calling qla1280_isr() from abort()
- Use spin_lock()/spin_unlock() in qla1280_intr_handler() - we
do not need to save/restore flags in the interrupt handler
- Enable interrupts early (before any mailbox access) in preparation
for cleaning up the mailbox handling
Rev 3.23.14 Beta March 14, 2002, Jes Sorensen
- Further cleanups. Remove all trace of QL_DEBUG_LEVEL_x and replace
it with proper use of dprintk().
- Make qla1280_print_scsi_cmd() and qla1280_dump_buffer() both take
a debug level argument to determine if data is to be printed
- Add KERN_* info to printk()
Rev 3.23.13 Beta March 14, 2002, Jes Sorensen
- Significant cosmetic cleanups
- Change debug code to use dprintk() and remove #if mess
Rev 3.23.12 Beta March 13, 2002, Jes Sorensen
- More cosmetic cleanups, fix places treating return as function
- use cpu_relax() in qla1280_debounce_register()
Rev 3.23.11 Beta March 13, 2002, Jes Sorensen
- Make it compile under 2.5.5
Rev 3.23.10 Beta October 1, 2001, Jes Sorensen
- Do no typecast short * to long * in QL1280BoardTbl, this
broke miserably on big endian boxes
Rev 3.23.9 Beta September 30, 2001, Jes Sorensen
- Remove pre 2.2 hack for checking for reentrance in interrupt handler
- Make data types used to receive from SCSI_{BUS,TCN,LUN}_32
unsigned int to match the types from struct scsi_cmnd
Rev 3.23.8 Beta September 29, 2001, Jes Sorensen
- Remove bogus timer_t typedef from qla1280.h
- Remove obsolete pre 2.2 PCI setup code, use proper #define's
for PCI_ values, call pci_set_master()
- Fix memleak of qla1280_buffer on module unload
- Only compile module parsing code #ifdef MODULE - should be
changed to use individual MODULE_PARM's later
- Remove dummy_buffer that was never modified nor printed
- ENTER()/LEAVE() are noops unless QL_DEBUG_LEVEL_3, hence remove
#ifdef QL_DEBUG_LEVEL_3/#endif around ENTER()/LEAVE() calls
- Remove \r from print statements, this is Linux, not DOS
- Remove obsolete QLA1280_{SCSILU,INTR,RING}_{LOCK,UNLOCK}
dummy macros
- Remove C++ compile hack in header file as Linux driver are not
supposed to be compiled as C++
- Kill MS_64BITS macro as it makes the code more readable
- Remove unnecessary flags.in_interrupts bit
Rev 3.23.7 Beta August 20, 2001, Jes Sorensen
- Dont' check for set flags on q->q_flag one by one in qla1280_next()
- Check whether the interrupt was generated by the QLA1280 before
doing any processing
- qla1280_status_entry(): Only zero out part of sense_buffer that
is not being copied into
- Remove more superflouous typecasts
- qla1280_32bit_start_scsi() replace home-brew memcpy() with memcpy()
Rev 3.23.6 Beta August 20, 2001, Tony Luck, Intel
- Don't walk the entire list in qla1280_putq_t() just to directly
grab the pointer to the last element afterwards
Rev 3.23.5 Beta August 9, 2001, Jes Sorensen
- Don't use SA_INTERRUPT, it's use is deprecated for this kinda driver
Rev 3.23.4 Beta August 8, 2001, Jes Sorensen
- Set dev->max_sectors to 1024
Rev 3.23.3 Beta August 6, 2001, Jes Sorensen
- Provide compat macros for pci_enable_device(), pci_find_subsys()
and scsi_set_pci_device()
- Call scsi_set_pci_device() for all devices
- Reduce size of kernel version dependent device probe code
- Move duplicate probe/init code to separate function
- Handle error if qla1280_mem_alloc() fails
- Kill OFFSET() macro and use Linux's PCI definitions instead
- Kill private structure defining PCI config space (struct config_reg)
- Only allocate I/O port region if not in MMIO mode
- Remove duplicate (unused) sanity check of sife of srb_t
Rev 3.23.2 Beta August 6, 2001, Jes Sorensen
- Change home-brew memset() implementations to use memset()
- Remove all references to COMTRACE() - accessing a PC's COM2 serial
port directly is not legal under Linux.
Rev 3.23.1 Beta April 24, 2001, Jes Sorensen
- Remove pre 2.2 kernel support
- clean up 64 bit DMA setting to use 2.4 API (provide backwards compat)
- Fix MMIO access to use readl/writel instead of directly
dereferencing pointers
- Nuke MSDOS debugging code
- Change true/false data types to int from uint8_t
- Use int for counters instead of uint8_t etc.
- Clean up size & byte order conversion macro usage
Rev 3.23 Beta January 11, 2001 BN Qlogic
- Added check of device_id when handling non
QLA12160s during detect().
Rev 3.22 Beta January 5, 2001 BN Qlogic
- Changed queue_task() to schedule_work()
for kernels 2.4.0 and higher.
Note: 2.4.0-testxx kernels released prior to
the actual 2.4.0 kernel release on January 2001
will get compile/link errors with schedule_work().
Please update your kernel to released 2.4.0 level,
or comment lines in this file flagged with 3.22
to resolve compile/link error of schedule_work().
- Added -DCONFIG_SMP in addition to -D__SMP__
in Makefile for 2.4.0 builds of driver as module.
Rev 3.21 Beta January 4, 2001 BN Qlogic
- Changed criteria of 64/32 Bit mode of HBA
operation according to BITS_PER_LONG rather
than HBA's NVRAM setting of >4Gig memory bit;
so that the HBA auto-configures without the need
to setup each system individually.
Rev 3.20 Beta December 5, 2000 BN Qlogic
- Added priority handling to IA-64 onboard SCSI
ISP12160 chip for kernels greater than 2.3.18.
- Added irqrestore for qla1280_intr_handler.
- Enabled /proc/scsi/qla1280 interface.
- Clear /proc/scsi/qla1280 counters in detect().
Rev 3.19 Beta October 13, 2000 BN Qlogic
- Declare driver_template for new kernel
(2.4.0 and greater) scsi initialization scheme.
- Update /proc/scsi entry for 2.3.18 kernels and
above as qla1280
Rev 3.18 Beta October 10, 2000 BN Qlogic
- Changed scan order of adapters to map
the QLA12160 followed by the QLA1280.
Rev 3.17 Beta September 18, 2000 BN Qlogic
- Removed warnings for 32 bit 2.4.x compiles
- Corrected declared size for request and response
DMA addresses that are kept in each ha
Rev. 3.16 Beta August 25, 2000 BN Qlogic
- Corrected 64 bit addressing issue on IA-64
where the upper 32 bits were not properly
passed to the RISC engine.
Rev. 3.15 Beta August 22, 2000 BN Qlogic
- Modified qla1280_setup_chip to properly load
ISP firmware for greater that 4 Gig memory on IA-64
Rev. 3.14 Beta August 16, 2000 BN Qlogic
- Added setting of dma_mask to full 64 bit
if flags.enable_64bit_addressing is set in NVRAM
Rev. 3.13 Beta August 16, 2000 BN Qlogic
- Use new PCI DMA mapping APIs for 2.4.x kernel
Rev. 3.12 July 18, 2000 Redhat & BN Qlogic
- Added check of pci_enable_device to detect() for 2.3.x
- Use pci_resource_start() instead of
pdev->resource[0].start in detect() for 2.3.x
- Updated driver version
Rev. 3.11 July 14, 2000 BN Qlogic
- Updated SCSI Firmware to following versions:
qla1x80: 8.13.08
qla1x160: 10.04.08
- Updated driver version to 3.11
Rev. 3.10 June 23, 2000 BN Qlogic
- Added filtering of AMI SubSys Vendor ID devices
Rev. 3.9
- DEBUG_QLA1280 undefined and new version BN Qlogic
Rev. 3.08b May 9, 2000 MD Dell
- Added logic to check against AMI subsystem vendor ID
Rev. 3.08 May 4, 2000 DG Qlogic
- Added logic to check for PCI subsystem ID.
Rev. 3.07 Apr 24, 2000 DG & BN Qlogic
- Updated SCSI Firmware to following versions:
qla12160: 10.01.19
qla1280: 8.09.00
Rev. 3.06 Apr 12, 2000 DG & BN Qlogic
- Internal revision; not released
Rev. 3.05 Mar 28, 2000 DG & BN Qlogic
- Edit correction for virt_to_bus and PROC.
Rev. 3.04 Mar 28, 2000 DG & BN Qlogic
- Merge changes from ia64 port.
Rev. 3.03 Mar 28, 2000 BN Qlogic
- Increase version to reflect new code drop with compile fix
of issue with inclusion of linux/spinlock for 2.3 kernels
Rev. 3.02 Mar 15, 2000 BN Qlogic
- Merge qla1280_proc_info from 2.10 code base
Rev. 3.01 Feb 10, 2000 BN Qlogic
- Corrected code to compile on a 2.2.x kernel.
Rev. 3.00 Jan 17, 2000 DG Qlogic
- Added 64-bit support.
Rev. 2.07 Nov 9, 1999 DG Qlogic
- Added new routine to set target parameters for ISP12160.
Rev. 2.06 Sept 10, 1999 DG Qlogic
- Added support for ISP12160 Ultra 3 chip.
Rev. 2.03 August 3, 1999 Fred Lewis, Intel DuPont
- Modified code to remove errors generated when compiling with
Cygnus IA64 Compiler.
- Changed conversion of pointers to unsigned longs instead of integers.
- Changed type of I/O port variables from uint32_t to unsigned long.
- Modified OFFSET macro to work with 64-bit as well as 32-bit.
- Changed sprintf and printk format specifiers for pointers to %p.
- Changed some int to long type casts where needed in sprintf & printk.
- Added l modifiers to sprintf and printk format specifiers for longs.
- Removed unused local variables.
Rev. 1.20 June 8, 1999 DG, Qlogic
Changes to support RedHat release 6.0 (kernel 2.2.5).
- Added SCSI exclusive access lock (io_request_lock) when accessing
the adapter.
- Added changes for the new LINUX interface template. Some new error
handling routines have been added to the template, but for now we
will use the old ones.
- Initial Beta Release.
*****************************************************************************/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/blk.h>
#include <linux/workqueue.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/byteorder.h>
#include <asm/processor.h>
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z))
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,18)
#include <linux/pci_ids.h>
#endif
#include "scsi.h"
#include "hosts.h"
#define UNIQUE_FW_NAME
#include "qla1280.h"
#include "ql12160_fw.h" /* ISP RISC codes */
#include "ql1280_fw.h"
/*
* Compile time Options:
* 0 - Disable and 1 - Enable
*/
#define QL1280_TARGET_MODE_SUPPORT 0 /* Target mode support */
#define QL1280_LUN_SUPPORT 0
#define WATCHDOGTIMER 0
#define MEMORY_MAPPED_IO 0
#define DEBUG_QLA1280_INTR 0
#define USE_NVRAM_DEFAULTS 0
#define DEBUG_PRINT_NVRAM 0
#define LOADING_RISC_ACTIVITY 0
#define AUTO_ESCALATE_RESET 0 /* Automatically escalate resets */
#define AUTO_ESCALATE_ABORT 0 /* Automatically escalate aborts */
#define STOP_ON_ERROR 0 /* Stop on aborts and resets */
#define STOP_ON_RESET 0
#define STOP_ON_ABORT 0
#define QLA1280_PROFILE 1 /* 3.20 */
#define DEBUG_QLA1280 0
/*
* Missing PCI ID's
*/
#ifndef PCI_DEVICE_ID_QLOGIC_ISP1080
#define PCI_DEVICE_ID_QLOGIC_ISP1080 0x1080
#endif
#ifndef PCI_DEVICE_ID_QLOGIC_ISP1240
#define PCI_DEVICE_ID_QLOGIC_ISP1240 0x1240
#endif
#ifndef PCI_DEVICE_ID_QLOGIC_ISP1280
#define PCI_DEVICE_ID_QLOGIC_ISP1280 0x1280
#endif
#ifndef PCI_DEVICE_ID_QLOGIC_ISP10160
#define PCI_DEVICE_ID_QLOGIC_ISP10160 0x1016
#endif
#ifndef PCI_DEVICE_ID_QLOGIC_ISP12160
#define PCI_DEVICE_ID_QLOGIC_ISP12160 0x1216
#endif
#ifndef PCI_VENDOR_ID_AMI
#define PCI_VENDOR_ID_AMI 0x101e
#endif
#if (BITS_PER_LONG == 64) || defined CONFIG_HIGHMEM
#define QLA_64BIT_PTR 1
#endif
/* 3.16 */
#ifdef QLA_64BIT_PTR
#define pci_dma_lo32(a) (a & 0xffffffff)
#define pci_dma_hi32(a) (a >> 32)
#else
#define pci_dma_lo32(a) (a & 0xffffffff)
#define pci_dma_hi32(a) 0
#endif
#define NVRAM_DELAY() udelay(500) /* 2 microsecond delay */
#define CACHE_FLUSH(a) RD_REG_WORD(a)
#define INVALID_HANDLE (MAX_OUTSTANDING_COMMANDS + 1)
/*
* Compat macros
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
#define pci_set_dma_mask(dev, mask) dev->dma_mask = mask;
#define pci_present() pcibios_present()
#define pci_enable_device(pdev) 0
#define pci_find_subsys(id, dev, sid, sdev, pdev) pci_find_device(id,dev,pdev)
#define scsi_set_pci_device(host, pdev)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
typedef unsigned long dma_addr_t;
static inline void *
pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
dma_addr_t * dma_handle)
{
void *virt_ptr;
virt_ptr = kmalloc(size, GFP_KERNEL);
if (!virt_ptr)
return NULL;
*dma_handle = virt_to_bus(virt_ptr);
return virt_ptr;
}
#define pci_free_consistent(cookie, size, ptr, dma_ptr) kfree(ptr)
#define pci_map_single(cookie, address, size, dir) virt_to_bus(address)
#define pci_map_sg(cookie, scatter, ents, dir) ents
#define pci_unmap_single(cookie, address, size, dir)
#define pci_unmap_sg(cookie, scatter, ents, dir)
#define pci_resource_start(dev, i) dev->base_address[i]
#endif
/*
* QLogic Driver Support Function Prototypes.
*/
static void qla1280_done(struct scsi_qla_host *, srb_t **, srb_t **);
static void qla1280_next(struct scsi_qla_host *, scsi_lu_t *, int);
static void qla1280_putq_t(scsi_lu_t *, srb_t *);
static void qla1280_done_q_put(srb_t *, srb_t **, srb_t **);
static int qla1280_slave_configure(Scsi_Device *);
#if STOP_ON_ERROR
static void qla1280_panic(char *, struct Scsi_Host *host);
#endif
static void qla1280_abort_queue_single(struct scsi_qla_host *, int, int,
int, uint32_t);
static int qla1280_return_status(sts_entry_t * sts, Scsi_Cmnd * cp);
static void qla1280_removeq(scsi_lu_t * q, srb_t * sp);
static void qla1280_mem_free(struct scsi_qla_host *ha);
void qla1280_do_dpc(void *p);
#ifdef MODULE
static char *qla1280_get_token(char *, char *);
#endif
static inline void qla1280_enable_intrs(struct scsi_qla_host *);
static inline void qla1280_disable_intrs(struct scsi_qla_host *);
/*
* QLogic ISP1280 Hardware Support Function Prototypes.
*/
static int qla1280_initialize_adapter(struct scsi_qla_host *ha);
static int qla1280_enable_tgt(struct scsi_qla_host *, int);
static int qla1280_isp_firmware(struct scsi_qla_host *);
static int qla1280_pci_config(struct scsi_qla_host *);
static int qla1280_chip_diag(struct scsi_qla_host *);
static int qla1280_setup_chip(struct scsi_qla_host *);
static int qla1280_init_rings(struct scsi_qla_host *);
static int qla1280_nvram_config(struct scsi_qla_host *);
static int qla1280_mailbox_command(struct scsi_qla_host *,
uint8_t, uint16_t *);
static int qla1280_bus_reset(struct scsi_qla_host *, int);
static int qla1280_device_reset(struct scsi_qla_host *, int, int);
static int qla1280_abort_device(struct scsi_qla_host *, int, int, int);
static int qla1280_abort_command(struct scsi_qla_host *, srb_t *);
static int qla1280_abort_isp(struct scsi_qla_host *);
static int qla1280_64bit_start_scsi(struct scsi_qla_host *, srb_t *);
static int qla1280_32bit_start_scsi(struct scsi_qla_host *, srb_t *);
static void qla1280_nv_write(struct scsi_qla_host *, uint16_t);
static void qla1280_poll(struct scsi_qla_host *);
static void qla1280_reset_adapter(struct scsi_qla_host *);
static void qla1280_marker(struct scsi_qla_host *, int, int, int, u8);
static void qla1280_isp_cmd(struct scsi_qla_host *);
static void qla1280_isr(struct scsi_qla_host *, srb_t **, srb_t **);
static void qla1280_rst_aen(struct scsi_qla_host *);
static void qla1280_status_entry(struct scsi_qla_host *, sts_entry_t *,
srb_t **, srb_t **);
static void qla1280_error_entry(struct scsi_qla_host *, response_t *,
srb_t **, srb_t **);
static void qla1280_restart_queues(struct scsi_qla_host *);
static void qla1280_abort_queues(struct scsi_qla_host *);
static uint16_t qla1280_get_nvram_word(struct scsi_qla_host *, uint32_t);
static uint16_t qla1280_nvram_request(struct scsi_qla_host *, uint32_t);
static uint16_t qla1280_debounce_register(volatile uint16_t *);
static request_t *qla1280_req_pkt(struct scsi_qla_host *);
static int qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *,
unsigned int);
static int qla1280_mem_alloc(struct scsi_qla_host *ha);
static void qla12160_get_target_parameters(struct scsi_qla_host *,
uint32_t, uint32_t, uint32_t);
#if QL1280_LUN_SUPPORT
static void qla1280_enable_lun(struct scsi_qla_host *, int, int);
#endif
#if QL1280_TARGET_MODE_SUPPORT
static void qla1280_notify_ack(struct scsi_qla_host *, notify_entry_t *);
static void qla1280_immed_notify(struct scsi_qla_host *, notify_entry_t *);
static void qla1280_accept_io(struct scsi_qla_host *, ctio_ret_entry_t *);
static void qla1280_64bit_continue_io(struct scsi_qla_host *, atio_entry_t *,
uint32_t, paddr32_t *);
static void qla1280_32bit_continue_io(struct scsi_qla_host *, atio_entry_t *,
uint32_t, paddr32_t *);
static void qla1280_atio_entry(struct scsi_qla_host *, atio_entry_t *);
static void qla1280_notify_entry(struct scsi_qla_host *, notify_entry_t *);
#endif /* QLA1280_TARGET_MODE_SUPPORT */
#ifdef QL_DEBUG_ROUTINES
/*
* Driver Debug Function Prototypes.
*/
static u8 qla1280_getbyte(u8 *);
static u16 qla1280_getword(u16 *);
static u32 qla1280_getdword(u32 *);
static void qla1280_putbyte(u8 *, u8);
static void qla1280_putword(u16 *, u8);
static void qla1280_putdword(u32 *, u32);
static void __qla1280_print_scsi_cmd(Scsi_Cmnd * cmd);
static void __qla1280_dump_buffer(char *, u32);
#endif
/*
* insmod needs to find the variable and make it point to something
*/
#ifdef MODULE
static char *options = NULL;
/* insmod qla1280 options=verbose" */
MODULE_PARM(options, "s");
#endif
MODULE_LICENSE("GPL");
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
/*
* Our directory Entry in /proc/scsi for the user to
* access the driver.
*/
/* Need to add in proc_fs.h PROC_SCSI_QL1280 */
#define PROC_SCSI_QL1280 PROC_SCSI_QLOGICISP
struct proc_dir_entry proc_scsi_qla1280 = {
PROC_SCSI_QL1280, 7, "qla1280",
S_IFDIR | S_IRUGO | S_IXUGO, 2,
0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
#endif
/* We use the Scsi_Pointer structure that's included with each command
* SCSI_Cmnd as a scratchpad for our SRB.
*
* SCp will always point to the SRB structure (defined in qla1280.h).
* It is define as follows:
* - SCp.ptr -- > pointer back to the cmd
* - SCp.this_residual --> used as forward pointer to next srb
* - SCp.buffer --> used as backward pointer to next srb
* - SCp.buffers_residual --> used as flags field
* - SCp.have_data_in --> not used
* - SCp.sent_command --> not used
* - SCp.phase --> not used
*/
#define CMD_SP(Cmnd) &Cmnd->SCp
#define CMD_CDBLEN(Cmnd) Cmnd->cmd_len
#define CMD_CDBP(Cmnd) Cmnd->cmnd
#define CMD_SNSP(Cmnd) Cmnd->sense_buffer
#define CMD_SNSLEN(Cmnd) sizeof(Cmnd->sense_buffer)
#define CMD_RESULT(Cmnd) Cmnd->result
#define CMD_HANDLE(Cmnd) Cmnd->host_scribble
/*****************************************/
/* ISP Boards supported by this driver */
/*****************************************/
#define NUM_OF_ISP_DEVICES 6
struct qla_boards {
unsigned char bdName[9]; /* Board ID String */
unsigned long device_id; /* Device PCI ID */
int numPorts; /* Number of SCSI ports */
unsigned short *fwcode; /* pointer to FW array */
unsigned short *fwlen; /* number of words in array */
unsigned short *fwstart; /* start address for F/W */
unsigned char *fwver; /* Ptr to F/W version array */
};
struct qla_boards ql1280_board_tbl[NUM_OF_ISP_DEVICES] = {
/* Name , Board PCI Device ID, Number of ports */
{"QLA12160 ", PCI_DEVICE_ID_QLOGIC_ISP12160, 2,
&fw12160i_code01[0], &fw12160i_length01,
&fw12160i_addr01, &fw12160i_version_str[0]},
{"QLA1080 ", PCI_DEVICE_ID_QLOGIC_ISP1080, 1,
&fw1280ei_code01[0], &fw1280ei_length01,
&fw1280ei_addr01, &fw1280ei_version_str[0]},
{"QLA1240 ", PCI_DEVICE_ID_QLOGIC_ISP1240, 2,
&fw1280ei_code01[0], &fw1280ei_length01,
&fw1280ei_addr01, &fw1280ei_version_str[0]},
{"QLA1280 ", PCI_DEVICE_ID_QLOGIC_ISP1280, 2,
&fw1280ei_code01[0], &fw1280ei_length01,
&fw1280ei_addr01, &fw1280ei_version_str[0]},
{"QLA10160 ", PCI_DEVICE_ID_QLOGIC_ISP10160, 1,
&fw12160i_code01[0], &fw12160i_length01,
&fw12160i_addr01, &fw12160i_version_str[0]},
{" ", 0, 0}
};
static int qla1280_verbose = 1;
static struct scsi_qla_host *qla1280_hostlist = NULL;
#if QLA1280_PROFILE
static int qla1280_buffer_size = 0;
static char *qla1280_buffer = NULL;
#endif
#if DEBUG_QLA1280
static int ql_debug_print = 1;
char debug_buff[80];
#define DEBUG(x) x
static int ql_debug_level = 0;
#define dprintk(level, format, a...) \
if ((ql_debug_level >= level) && ql_debug_print) printk(KERN_DEBUG format, ##a)
#define qla1280_dump_buffer(level, buf, size) \
if (ql_debug_level >= level) __qla1280_dump_buffer(buf, size)
#define qla1280_dump_print_cmd(level, cmd) \
if (ql_debug_level >= level) __qla1280_print_scsi_cmd(cmd)
#else
#define DEBUG(x)
#define ql_debug_level 0
#define dprintk(level, format, a...) do{}while(0)
#define qla1280_dump_buffer(a, b, c) do{}while(0)
#define qla1280_print_scsi_cmd(a, b) do{}while(0)
#endif
#define ENTER(x) dprintk(3, "qla1280 : Entering %s()\n", x);
#define LEAVE(x) dprintk(3, "qla1280 : Leaving %s()\n", x);
#define ENTER_INTR(x) dprintk(3, "qla1280 : Entering %s()\n", x);
#define LEAVE_INTR(x) dprintk(3, "qla1280 : Leaving %s()\n", x);
#define SCSI_BUS_32(scp) scp->device->channel
#define SCSI_TCN_32(scp) scp->device->id
#define SCSI_LUN_32(scp) scp->device->lun
/****************************************************************************/
/* LINUX - Loadable Module Functions. */
/****************************************************************************/
/*************************************************************************
* qla1280_set_info
*
* Description:
* Set parameters for the driver from the /proc filesystem.
*
* Returns:
*************************************************************************/
int
qla1280_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
{
return -ENOSYS; /* Currently this is a no-op */
}
/*************************************************************************
* qla1280_proc_info
*
* Description:
* Return information to handle /proc support for the driver.
*
* buffer - ptrs to a page buffer
*
* Returns:
*************************************************************************/
#define PROC_BUF &qla1280_buffer[len]
int
qla1280_proc_info(char *buffer, char **start, off_t offset, int length,
int hostno, int inout)
{
#if QLA1280_PROFILE
struct Scsi_Host *host;
struct scsi_qla_host *ha;
int size = 0;
scsi_lu_t *up;
int len = 0;
struct qla_boards *bdp;
uint32_t b, t, l;
host = NULL;
/* Find the host that was specified */
for (ha = qla1280_hostlist; (ha != NULL) && ha->host->host_no != hostno;
ha = ha->next) ;
/* if host wasn't found then exit */
if (!ha) {
size = sprintf(buffer, "Can't find adapter for host "
"number %d\n", hostno);
if (size > length) {
return size;
} else {
return 0;
}
}
host = ha->host;
if (inout == TRUE) { /* Has data been written to the file? */
printk(KERN_INFO
"qla1280_proc: has data been written to the file.\n");
return qla1280_set_info(buffer, length, host);
}
/*
* if our old buffer is the right size use it otherwise
* allocate a new one.
*/
if (qla1280_buffer_size != PAGE_SIZE) {
/* deallocate this buffer and get a new one */
if (qla1280_buffer != NULL) {
free_page((unsigned long)qla1280_buffer);
qla1280_buffer_size = 0;
}
qla1280_buffer = (char *)get_zeroed_page(GFP_KERNEL);
}
if (qla1280_buffer == NULL) {
size = sprintf(buffer, "qla1280 - kmalloc error at line %d\n",
__LINE__);
return size;
}
/* save the size of our buffer */
qla1280_buffer_size = PAGE_SIZE;
/* 3.20 clear the buffer we use for proc display */
memset(qla1280_buffer, 0, PAGE_SIZE);
/* start building the print buffer */
bdp = &ql1280_board_tbl[ha->devnum];
size = sprintf(PROC_BUF,
"QLogic PCI to SCSI Adapter for ISP 1280/12160:\n"
" Firmware version: %2d.%02d.%02d, Driver version %s\n",
bdp->fwver[0], bdp->fwver[1], bdp->fwver[2],
QLA1280_VERSION);
len += size;
size = sprintf(PROC_BUF, "SCSI Host Adapter Information: %s\n",
bdp->bdName);
len += size;
size = sprintf(PROC_BUF, "Request Queue = 0x%p, Response Queue = 0x%p\n",
(void *)ha->request_dma, (void *)ha->response_dma);
len += size;
size = sprintf(PROC_BUF, "Request Queue count= 0x%x, Response "
"Queue count= 0x%x\n",
REQUEST_ENTRY_CNT, RESPONSE_ENTRY_CNT);
len += size;
size = sprintf(PROC_BUF, "Number of pending commands = 0x%lx\n",
ha->actthreads);
len += size;
size = sprintf(PROC_BUF, "Number of queued commands = 0x%lx\n",
ha->qthreads);
len += size;
size = sprintf(PROC_BUF, "Number of free request entries = %d\n",
ha->req_q_cnt);
len += size;
size = sprintf(PROC_BUF, "\n"); /* 1 */
len += size;
size = sprintf(PROC_BUF, "SCSI device Information:\n");
len += size;
/* scan for all equipment stats */
for (b = 0; b < MAX_BUSES; b++)
for (t = 0; t < MAX_TARGETS; t++) {
for (l = 0; l < MAX_LUNS; l++) {
up = LU_Q(ha, b, t, l);
if (up == NULL)
continue;
/* unused device/lun */
if (up->io_cnt == 0 || up->io_cnt < 2)
continue;
/* total reads since boot */
/* total writes since boot */
/* total requests since boot */
size = sprintf (PROC_BUF,
"(%2d:%2d:%2d): Total reqs %ld,",
b, t, l, up->io_cnt);
len += size;
/* current number of pending requests */
size = sprintf(PROC_BUF, " Pend reqs %d,",
up->q_outcnt);
len += size;
#if 0
/* avg response time */
size = sprintf(PROC_BUF, " Avg resp time %ld%%,",
(up->resp_time / up->io_cnt) *
100);
len += size;
/* avg active time */
size = sprintf(PROC_BUF,
" Avg active time %ld%%\n",
(up->act_time / up->io_cnt) * 100);
#else
size = sprintf(PROC_BUF, "\n");
#endif
len += size;
}
if (len >= qla1280_buffer_size)
break;
}
if (len >= qla1280_buffer_size) {
printk(KERN_WARNING
"qla1280: Overflow buffer in qla1280_proc.c\n");
}
if (offset > len - 1) {
free_page((unsigned long) qla1280_buffer);
qla1280_buffer = NULL;
qla1280_buffer_size = length = 0;
*start = NULL;
} else {
*start = &qla1280_buffer[offset]; /* Start of wanted data */
if (len - offset < length) {
length = len - offset;
}
}
return length;
#else
return 0;
#endif
}
/**************************************************************************
* qla1280_do_device_init
* This routine will register the device with the SCSI subsystem,
* initialize the host adapter structure and call the device init
* routines.
*
* Input:
* pdev - pointer to struct pci_dev for adapter
* template - pointer to SCSI template
* devnum - the device number
* bdp - pointer to struct _qlaboards
* num_hosts - the host number
*
* Returns:
* host - pointer to SCSI host structure
**************************************************************************/
struct Scsi_Host *
qla1280_do_device_init(struct pci_dev *pdev,
Scsi_Host_Template * template,
int devnum, struct qla_boards *bdp, int num_hosts)
{
struct Scsi_Host *host;
struct scsi_qla_host *ha;
struct device_reg *reg;
printk("qla1x160: Initializing ISP12160 on PCI bus %i, dev %i, irq %i\n",
pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->irq);
host = scsi_register(template, sizeof(struct scsi_qla_host));
if (!host) {
printk(KERN_WARNING
"qla1280: Failed to register host, aborting.\n");
goto error;
}
scsi_set_device(host, &pdev->dev);
ha = (struct scsi_qla_host *)host->hostdata;
/* Clear our data area */
memset(ha, 0, sizeof(struct scsi_qla_host));
/* Sanitize the information from PCI BIOS. */
host->irq = pdev->irq;
ha->pci_bus = pdev->bus->number;
ha->pci_device_fn = pdev->devfn;
ha->pdev = pdev;
ha->device_id = bdp->device_id;
ha->devnum = devnum; /* specifies microcode load address */
if (qla1280_mem_alloc(ha)) {
printk(KERN_INFO "qla1x160: Failed to get memory\n");
goto error;
}
ha->ports = bdp->numPorts;
/* following needed for all cases of OS versions */
ha->host = host;
ha->host_no = host->host_no;
host->can_queue = 0xfffff; /* unlimited */
host->cmd_per_lun = 1;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
host->base = (unsigned char *)ha->mmpbase;
#else
host->base = (unsigned long)ha->mmpbase;
#endif
host->max_channel = bdp->numPorts - 1;
host->max_lun = MAX_LUNS - 1;
host->max_id = MAX_TARGETS;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
host->max_sectors = 1024;
#endif
ha->instance = num_hosts;
host->unique_id = ha->instance;
if (qla1280_pci_config(ha)) {
printk(KERN_INFO "qla1x160: Unable to configure PCI\n");
goto error_mem_alloced;
}
/* Disable ISP interrupts. */
qla1280_disable_intrs(ha);
/* Register the IRQ with Linux (sharable) */
if (request_irq(host->irq, qla1280_intr_handler, SA_SHIRQ,
"qla1280", ha)) {
printk("qla1280 : Failed to reserve interrupt %d already "
"in use\n", host->irq);
goto error_unmap;
}
#if !MEMORY_MAPPED_IO
/* Register the I/O space with Linux */
if (!request_region(host->io_port, 0xff, "qla1280")) {
printk("qla1280 : Failed to reserve i/o region 0x%04lx-0x%04lx"
" already in use\n",
host->io_port, host->io_port + 0xff);
goto error_irq;
}
#endif
reg = ha->iobase;
/* load the F/W, read paramaters, and init the H/W */
if (qla1280_initialize_adapter(ha)) {
printk(KERN_INFO "qla1x160:Failed to initialize adapter\n");
goto error_region;
}
/* set our host ID (need to do something about our two IDs) */
host->this_id = ha->bus_settings[0].id;
return host;
error_region:
#if !MEMORY_MAPPED_IO
release_region(host->io_port, 0xff);
#endif
error_irq:
free_irq(host->irq, ha);
error_unmap:
#if MEMORY_MAPPED_IO
if (ha->mmpbase)
iounmap((void *)(((unsigned long) ha->mmpbase) & PAGE_MASK));
#endif
error_mem_alloced:
qla1280_mem_free(ha);
error:
if (host) {
scsi_unregister(host);
}
return NULL;
}
/**************************************************************************
* qla1280_detect
* This routine will probe for Qlogic 1280 SCSI host adapters.
* It returns the number of host adapters of a particular
* type that were found. It also initialize all data necessary for
* the driver. It is passed-in the host number, so that it
* knows where its first entry is in the scsi_hosts[] array.
*
* Input:
* template - pointer to SCSI template
*
* Returns:
* num - number of host adapters found.
**************************************************************************/
int
qla1280_detect(Scsi_Host_Template * template)
{
struct pci_dev *pdev = NULL;
struct Scsi_Host *host;
struct scsi_qla_host *ha, *cur_ha;
struct qla_boards *bdp;
uint16_t subsys_vendor, subsys_device;
int num_hosts = 0;
int devnum = 0;
ENTER("qla1280_detect");
if (sizeof(srb_t) > sizeof(Scsi_Pointer)) {
printk(KERN_WARNING
"qla1280_detect: [WARNING] srb_t too big\n");
return 0;
}
#ifdef MODULE
dprintk(1, "DEBUG: qla1280_detect starts at address = %p\n",
qla1280_detect);
/*
* If we are called as a module, the qla1280 pointer may not be null
* and it would point to our bootup string, just like on the lilo
* command line. IF not NULL, then process this config string with
* qla1280_setup
*
* Boot time Options
* To add options at boot time add a line to your lilo.conf file like:
* append="qla1280=verbose,max_tags:{{255,255,255,255},{255,255,255,255}}"
* which will result in the first four devices on the first two
* controllers being set to a tagged queue depth of 32.
*/
if (options)
qla1280_setup(options, NULL);
printk(KERN_WARNING
"qla1280: Please read the file /usr/src/linux/Documentation"
"/scsi/qla1280.txt\n"
"qla1280: to see the proper way to specify options to the qla1280 "
"module\n"
"qla1280: Specifically, don't use any commas when passing "
"arguments to\n"
"qla1280: insmod or else it might trash certain memory areas.\n");
#endif
if (!pci_present()) {
printk(KERN_INFO "scsi: PCI not present\n");
return 0;
}
bdp = &ql1280_board_tbl[0];
qla1280_hostlist = NULL;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
template->proc_dir = &proc_scsi_qla1280;
#else
template->proc_name = "qla1280";
#endif
/* 3.20 */
/* First Initialize QLA12160 on PCI Bus 1 Dev 2 */
while ((pdev = pci_find_subsys(PCI_VENDOR_ID_QLOGIC, bdp->device_id,
PCI_ANY_ID, PCI_ANY_ID, pdev))) {
/* find QLA12160 device on PCI bus=1 slot=2 */
if ((pdev->bus->number != 1) || (PCI_SLOT(pdev->devfn) != 2))
continue;
/* Bypass all AMI SUBSYS VENDOR IDs */
if (pdev->subsystem_vendor == PCI_VENDOR_ID_AMI) {
printk(KERN_INFO
"qla1x160: Skip AMI SubSys Vendor ID Chip\n");
continue;
}
if (pci_enable_device(pdev))
goto find_devices;
host = qla1280_do_device_init(pdev, template, devnum,
bdp, num_hosts);
if (!host)
continue;
ha = (struct scsi_qla_host *)host->hostdata;
/* this preferred device will always be the first one found */
cur_ha = qla1280_hostlist = ha;
num_hosts++;
}
find_devices:
pdev = NULL;
/* Try and find each different type of adapter we support */
for (devnum = 0; bdp->device_id != 0 && devnum < NUM_OF_ISP_DEVICES;
devnum++, bdp++) {
/* PCI_SUBSYSTEM_IDS supported */
while ((pdev = pci_find_subsys(PCI_VENDOR_ID_QLOGIC,
bdp->device_id, PCI_ANY_ID,
PCI_ANY_ID, pdev))) {
if (pci_enable_device(pdev))
continue;
/* found an adapter */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,18)
subsys_vendor = pdev->subsystem_vendor;
subsys_device = pdev->subsystem_device;
#else
pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID,
&subsys_vendor);
pci_read_config_word(pdev, PCI_SUBSYSTEM_ID,
&subsys_device);
#endif
/*
* skip QLA12160 already initialized on
* PCI Bus 1 Dev 2 since we already initialized
* and presented it
*/
if ((bdp->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160)&&
(pdev->bus->number == 1) &&
(PCI_SLOT(pdev->devfn) == 2))
continue;
/* Bypass all AMI SUBSYS VENDOR IDs */
if (subsys_vendor == PCI_VENDOR_ID_AMI) {
printk(KERN_INFO
"qla1x160: Skip AMI SubSys Vendor ID Chip\n");
continue;
}
printk(KERN_INFO
"qla1x160: Supported Device Found VID=%x "
"DID=%x SSVID=%x SSDID=%x\n", pdev->vendor,
pdev->device, subsys_vendor, subsys_device);
host = qla1280_do_device_init(pdev, template,
devnum, bdp, num_hosts);
if (!host)
continue;
ha = (struct scsi_qla_host *)host->hostdata;
if (qla1280_hostlist == NULL) {
cur_ha = qla1280_hostlist = ha;
} else {
cur_ha = qla1280_hostlist;
while (cur_ha->next != NULL)
cur_ha = cur_ha->next;
cur_ha->next = ha;
}
num_hosts++;
} /* end of WHILE */
} /* end of FOR */
LEAVE("qla1280_detect");
return num_hosts;
}
/**************************************************************************
* qla1280_release
* Free the passed in Scsi_Host memory structures prior to unloading the
* module.
**************************************************************************/
int
qla1280_release(struct Scsi_Host *host)
{
struct scsi_qla_host *ha = (struct scsi_qla_host *)host->hostdata;
ENTER("qla1280_release");
if (!ha->flags.online)
return 0;
/* turn-off interrupts on the card */
WRT_REG_WORD(&ha->iobase->ictrl, 0);
/* Detach interrupts */
if (host->irq)
free_irq(host->irq, ha);
#if MEMORY_MAPPED_IO
if (ha->mmpbase)
iounmap((void *)(((unsigned long) ha->mmpbase) & PAGE_MASK));
#else
/* release io space registers */
if (host->io_port)
release_region(host->io_port, 0xff);
#endif /* MEMORY_MAPPED_IO */
qla1280_mem_free(ha);
ENTER("qla1280_release");
return 0;
}
/**************************************************************************
* qla1280_info
* Return a string describing the driver.
**************************************************************************/
const char *
qla1280_info(struct Scsi_Host *host)
{
static char qla1280_scsi_name_buffer[125];
char *bp;
struct scsi_qla_host *ha;
struct qla_boards *bdp;
bp = &qla1280_scsi_name_buffer[0];
ha = (struct scsi_qla_host *)host->hostdata;
bdp = &ql1280_board_tbl[ha->devnum];
memset(bp, 0, sizeof(qla1280_scsi_name_buffer));
sprintf (bp,
"QLogic %s PCI to SCSI Host Adapter: bus %d device %d irq %d\n"
" Firmware version: %2d.%02d.%02d, Driver version %s",
&bdp->bdName[0], ha->pci_bus, (ha->pci_device_fn & 0xf8) >> 3,
host->irq, bdp->fwver[0], bdp->fwver[1], bdp->fwver[2],
QLA1280_VERSION);
return bp;
}
/**************************************************************************
* qla1200_queuecommand
* Queue a command to the controller.
*
* Note:
* The mid-level driver tries to ensures that queuecommand never gets invoked
* concurrently with itself or the interrupt handler (although the
* interrupt handler may call this routine as part of request-completion
* handling). Unfortunely, it sometimes calls the scheduler in interrupt
* context which is a big NO! NO!.
**************************************************************************/
int
qla1280_queuecommand(Scsi_Cmnd * cmd, void (*fn) (Scsi_Cmnd *))
{
struct scsi_qla_host *ha;
srb_t *sp;
struct Scsi_Host *host;
int bus, target, lun;
scsi_lu_t *q;
/*ENTER("qla1280_queuecommand");
*/
host = cmd->device->host;
ha = (struct scsi_qla_host *)host->hostdata;
/* send command to adapter */
sp = (srb_t *)CMD_SP(cmd);
sp->cmd = cmd;
cmd->scsi_done = fn;
if (cmd->flags == 0) { /* new command */
sp->flags = 0;
}
qla1280_print_scsi_cmd(5, cmd);
/* Generate LU queue on bus, target, LUN */
bus = SCSI_BUS_32(cmd);
target = SCSI_TCN_32(cmd);
lun = SCSI_LUN_32(cmd);
if ((q = LU_Q(ha, bus, target, lun)) == NULL) {
if ((q = (scsi_lu_t *)kmalloc(sizeof(struct scsi_lu),
GFP_ATOMIC))) {
LU_Q(ha, bus, target, lun) = q;
memset(q, 0, sizeof(struct scsi_lu));
dprintk(1, "Allocate new device queue 0x%p\n",
(void *)q);
} else {
CMD_RESULT(cmd) = DID_BUS_BUSY << 16;
qla1280_done_q_put(sp, &ha->done_q_first,
&ha->done_q_last);
/* 3.22 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) /* 3.22 */
schedule_work(&ha->run_qla_bh);
#else /* 3.22 */
schedule_work(&ha->run_qla_bh); /* 3.22 */
#endif /* 3.22 */
return 0;
}
}
/* Set an invalid handle until we issue the command to ISP */
/* then we will set the real handle value. */
CMD_HANDLE(cmd) = (unsigned char *)INVALID_HANDLE;
/* add the command to our queue */
ha->qthreads++;
qla1280_putq_t(q, sp);
dprintk(1, "qla1280_QC: t=%x CDB=%x I/OSize=0x%x haQueueCount=0x%lx\n",
target, cmd->cmnd[0], cmd->request_bufflen, ha->qthreads);
/* send command to adapter */
if (q->q_outcnt == 0)
qla1280_restart_queues(ha);
/*LEAVE("qla1280_queuecommand"); */
return 0;
}
/**************************************************************************
* qla1200_abort
* Abort the speciifed SCSI command(s).
**************************************************************************/
int
qla1280_abort(Scsi_Cmnd * cmd)
{
struct scsi_qla_host *ha;
srb_t *sp;
struct Scsi_Host *host;
unsigned int bus, target, lun;
scsi_lu_t *q;
int return_status = SCSI_ABORT_SUCCESS;
int found = 0;
int i;
unsigned char *handle;
u16 data;
ENTER("qla1280_abort");
ha = (struct scsi_qla_host *)cmd->device->host->hostdata;
host = cmd->device->host;
/* Get the SCSI request ptr */
sp = (srb_t *)CMD_SP(cmd);
handle = CMD_HANDLE(cmd);
if (qla1280_verbose)
printk(KERN_ERR "scsi(%li): ABORT Command=0x%p, handle=0x%p\n",
ha->host_no, (void *) cmd, (void *) handle);
/* Check for pending interrupts. */
if (handle == NULL) {
/* we never got this command */
printk(KERN_INFO "qla1280: Aborting a NULL handle\n");
return SCSI_ABORT_NOT_RUNNING; /* no action - we don't have command */
}
data = qla1280_debounce_register(&ha->iobase->istatus);
/*
* The io_request_lock is held when the reset handler is called, hence
* the interrupt handler cannot be running in parallel as it also
* grabs the lock. No reason to play funny games with set_bit() in
* order to test for interrupt handler entry as the driver used to
* do here.
* /Jes
*/
if (data & RISC_INT) {
/* put any pending command in done queue */
qla1280_isr(ha, &ha->done_q_first, &ha->done_q_last);
}
/*
* This seems unnecessary, it's not used below! / Jes
*/
#ifdef UNUSED
handle = CMD_HANDLE(cmd);
#endif
/* Generate LU queue on bus, target, LUN */
bus = SCSI_BUS_32(cmd);
target = SCSI_TCN_32(cmd);
lun = SCSI_LUN_32(cmd);
if ((q = LU_Q(ha, bus, target, lun)) == NULL) {
/* No lun queue -- command must not be active */
printk(KERN_WARNING "qla1280 (%d:%d:%d): No LUN queue for the "
"specified device\n", bus, target, lun);
return SCSI_ABORT_NOT_RUNNING; /* no action - we don't have command */
}
#if AUTO_ESCALATE_ABORT
if ((sp->flags & SRB_ABORTED)) {
dprintk(1, "qla1280_abort: Abort escalayted - returning "
"SCSI_ABORT_SNOOZE.\n");
return SCSI_ABORT_SNOOZE;
}
#endif
if ((sp->flags & SRB_ABORT_PENDING)) {
if (qla1280_verbose)
printk(KERN_WARNING
"scsi(): Command has a pending abort "
"message - ABORT_PENDING.\n");
return SCSI_ABORT_PENDING;
}
#if STOP_ON_ABORT
printk(KERN_WARNING "Scsi layer issued a ABORT command= 0x%p\n", cmd);
qla1280_print_scsi_cmd(2, cmd);
#endif
/*
* Normally, would would need to search our queue for the specified command
* but; since our sp contains the cmd ptr, we can just remove it from our
* LUN queue.
*/
if (!(sp->flags & SRB_SENT)) {
found++;
if (qla1280_verbose)
printk(KERN_WARNING
"scsi(): Command returned from queue "
"aborted.\n");
/* Remove srb from SCSI LU queue. */
qla1280_removeq(q, sp);
sp->flags |= SRB_ABORTED;
CMD_RESULT(cmd) = DID_ABORT << 16;
qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last);
return_status = SCSI_ABORT_SUCCESS;
} else { /* find the command in our active list */
for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
if (sp == ha->outstanding_cmds[i]) {
found++;
dprintk(1,
"qla1280: RISC aborting command.\n");
qla1280_abort_command(ha, sp);
return_status = SCSI_ABORT_PENDING;
break;
}
}
}
#if STOP_ON_ABORT
qla1280_panic("qla1280_abort", ha->host);
#endif
if (found == 0)
return_status = SCSI_ABORT_NOT_RUNNING; /* no action - we don't have command */
dprintk(1, "qla1280_abort: Aborted status returned = 0x%x.\n",
return_status);
if (ha->done_q_first)
qla1280_done(ha, &ha->done_q_first, &ha->done_q_last);
if (found)
qla1280_restart_queues(ha);
LEAVE("qla1280_abort");
return return_status;
}
int
qla1280_new_abort(Scsi_Cmnd * cmd)
{
struct scsi_qla_host *ha;
srb_t *sp;
struct Scsi_Host *host;
int bus, target, lun;
scsi_lu_t *q;
unsigned long cpu_flags;
int return_status = SCSI_ABORT_SUCCESS;
int found = 0;
int i;
unsigned char *handle;
u16 data;
ENTER("qla1280_abort");
host = cmd->device->host;
ha = (struct scsi_qla_host *)host->hostdata;
/* Get the SCSI request ptr */
sp = (srb_t *) CMD_SP(cmd);
handle = CMD_HANDLE(cmd);
if (qla1280_verbose)
printk(KERN_ERR "scsi(%li): ABORT Command=0x%p, handle=0x%p\n",
ha->host_no, cmd, handle);
/* Check for pending interrupts. */
if (handle == NULL) {
/* we never got this command */
printk(KERN_INFO "qla1280: Aborting a NULL handle\n");
return SUCCESS; /* no action - we don't have command */
}
spin_lock_irqsave (ha->host->host_lock, cpu_flags);
data = qla1280_debounce_register(&ha->iobase->istatus);
/*
* We grab the host lock in the interrupt handler to
* prevent racing here.
*
* Then again, running the interrupt handler from here is somewhat
* questionable.
* /Jes
*/
if (data & RISC_INT) {
/* put any pending command in done queue */
qla1280_isr(ha, &ha->done_q_first, &ha->done_q_last);
}
/* Generate LU queue on bus, target, LUN */
bus = SCSI_BUS_32(cmd);
target = SCSI_TCN_32(cmd);
lun = SCSI_LUN_32(cmd);
if ((q = LU_Q(ha, bus, target, lun)) == NULL) {
/* No lun queue -- command must not be active */
printk(KERN_WARNING "qla1280 (%d:%d:%d): No LUN queue for the "
"specified device\n", bus, target, lun);
return_status = SUCCESS; /* no action - we don't have command */
goto out;
}
if ((sp->flags & SRB_ABORT_PENDING)) {
if (qla1280_verbose)
printk(KERN_WARNING
"scsi(): Command has a pending abort "
"message - ABORT_PENDING.\n");
return_status = SCSI_ABORT_PENDING;
goto out;
}
#if STOP_ON_ABORT
printk(KERN_WARNING "Scsi layer issued a ABORT command= 0x%p\n", cmd);
qla1280_print_scsi_cmd(2, cmd);
#endif
/*
* Normally, would would need to search our queue for the specified command
* but; since our sp contains the cmd ptr, we can just remove it from our
* LUN queue.
*/
if (!(sp->flags & SRB_SENT)) {
found++;
if (qla1280_verbose)
printk(KERN_WARNING
"scsi(): Command returned from queue "
"aborted.\n");
/* Remove srb from SCSI LU queue. */
qla1280_removeq(q, sp);
sp->flags |= SRB_ABORTED;
CMD_RESULT(cmd) = DID_ABORT << 16;
qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last);
return_status = SUCCESS;
} else { /* find the command in our active list */
for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
if (sp == ha->outstanding_cmds[i]) {
found++;
dprintk(1,
"qla1280: RISC aborting command.\n");
qla1280_abort_command(ha, sp);
return_status = SCSI_ABORT_PENDING;
break;
}
}
}
#if STOP_ON_ABORT
qla1280_panic("qla1280_abort", ha->host);
#endif
if (found == 0)
return_status = SUCCESS; /* no action - we don't have the command */
dprintk(1, "qla1280_abort: Aborted status returned = 0x%x.\n",
return_status);
if (ha->done_q_first)
qla1280_done(ha, &ha->done_q_first, &ha->done_q_last);
if (found)
qla1280_restart_queues(ha);
out:
spin_unlock_irqrestore(ha->host->host_lock, cpu_flags);
LEAVE("qla1280_abort");
return return_status;
}
/**************************************************************************
* qla1200_reset
* The reset function will reset the SCSI bus and abort any executing
* commands.
*
* Input:
* cmd = Linux SCSI command packet of the command that cause the
* bus reset.
* flags = SCSI bus reset option flags (see scsi.h)
*
* Returns:
* DID_RESET in cmd.host_byte of aborted command(s)
*
* Note:
* Resetting the bus always succeeds - is has to, otherwise the
* kernel will panic! Try a surgical technique - sending a BUS
* DEVICE RESET message - on the offending target before pulling
* the SCSI bus reset line.
**************************************************************************/
int
qla1280_reset(Scsi_Cmnd * cmd, unsigned int flags)
{
struct scsi_qla_host *ha;
int bus, target, lun;
srb_t *sp;
typedef enum {
ABORT_DEVICE = 1,
DEVICE_RESET = 2,
BUS_RESET = 3,
ADAPTER_RESET = 4,
RESET_DELAYED = 5,
FAIL = 6
} action_t;
action_t action = ADAPTER_RESET;
u16 data;
scsi_lu_t *q;
int result;
ENTER("qla1280_reset");
if (qla1280_verbose)
printk(KERN_INFO "scsi(): Resetting Cmnd=0x%p, Handle=0x%p, "
"flags=0x%x\n", cmd, CMD_HANDLE(cmd), flags);
if (cmd == NULL) {
printk(KERN_WARNING
"(scsi?:?:?:?) Reset called with NULL Scsi_Cmnd "
"pointer, failing.\n");
return SCSI_RESET_SNOOZE;
}
ha = (struct scsi_qla_host *)cmd->device->host->hostdata;
sp = (srb_t *)CMD_SP(cmd);
#if STOP_ON_RESET
qla1280_panic("qla1280_reset", ha->host);
#endif
/* Check for pending interrupts. */
data = qla1280_debounce_register(&ha->iobase->istatus);
/*
* The io_request_lock is held when the reset handler is called, hence
* the interrupt handler cannot be running in parallel as it also
* grabs the lock. /Jes
*/
if (data & RISC_INT)
qla1280_isr(ha, &ha->done_q_first, &ha->done_q_last);
/*
* Determine the suggested action that the mid-level driver wants
* us to perform.
*/
if (CMD_HANDLE(cmd) == NULL) {
/*
* if mid-level driver called reset with a orphan SCSI_Cmnd
* (i.e. a command that's not pending), so perform the
* function specified.
*/
if (flags & SCSI_RESET_SUGGEST_HOST_RESET)
action = ADAPTER_RESET;
else
action = BUS_RESET;
} else {
/*
* Mid-level driver has called reset with this SCSI_Cmnd and
* its pending.
*/
if (flags & SCSI_RESET_SUGGEST_HOST_RESET)
action = ADAPTER_RESET;
else if (flags & SCSI_RESET_SUGGEST_BUS_RESET)
action = BUS_RESET;
else
action = DEVICE_RESET;
}
bus = SCSI_BUS_32(cmd);
target = SCSI_TCN_32(cmd);
lun = SCSI_LUN_32(cmd);
q = LU_Q(ha, bus, target, lun);
#if AUTO_ESCALATE_RESET
if ((action & DEVICE_RESET) && (q->q_flag & QLA1280_QRESET)) {
printk(KERN_INFO
"qla1280(%ld): Bus device reset already sent to "
"device, escalating.\n", ha->host_no);
action = BUS_RESET;
}
if ((action & DEVICE_RESET) && (sp->flags & SRB_ABORT_PENDING)) {
printk(KERN_INFO
"qla1280(%ld):Have already attempted to reach "
"device with abort device\n", ha->host_no);
printk(KERN_INFO "qla1280(%ld):message, will escalate to BUS "
"RESET.\n", ha->host_no);
action = BUS_RESET;
}
#endif
/*
* By this point, we want to already know what we are going to do,
* so we only need to perform the course of action.
*/
result = SCSI_RESET_ERROR;
switch (action) {
case FAIL:
break;
case RESET_DELAYED:
result = SCSI_RESET_PENDING;
break;
case ABORT_DEVICE:
ha->flags.in_reset = TRUE;
if (qla1280_verbose)
printk(KERN_INFO
"scsi(%ld:%d:%d:%d): Queueing abort device "
"command.\n", ha->host_no, bus, target, lun);
qla1280_abort_queue_single(ha, bus, target, lun, DID_ABORT);
if (qla1280_abort_device(ha, bus, target, lun) == 0)
result = SCSI_RESET_PENDING;
break;
case DEVICE_RESET:
if (qla1280_verbose)
printk(KERN_INFO
"scsi(%ld:%d:%d:%d): Queueing device reset "
"command.\n", ha->host_no, bus, target, lun);
ha->flags.in_reset = TRUE;
for (lun = 0; lun < MAX_LUNS; lun++)
qla1280_abort_queue_single(ha, bus, target, lun,
DID_ABORT);
if (qla1280_device_reset(ha, bus, target) == 0)
result = SCSI_RESET_PENDING;
q->q_flag |= QLA1280_QRESET;
break;
case BUS_RESET:
if (qla1280_verbose)
printk(KERN_INFO "qla1280(%ld:%d:%d:%d): Issuing BUS "
"DEVICE RESET.\n", ha->host_no, bus, target,
lun);
ha->flags.in_reset = TRUE;
for (target = 0; target < MAX_TARGETS; target++)
for (lun = 0; lun < MAX_LUNS; lun++)
qla1280_abort_queue_single(ha, bus, target,
lun, DID_RESET);
qla1280_bus_reset(ha, bus);
/*
* The bus reset routine returns all the outstanding commands
* back with "DID_RESET" in the status field after a short
* delay by the firmware. If the mid-level time out the SCSI
* reset before our delay we may need to ignore it.
*/
/* result = SCSI_RESET_PENDING | SCSI_RESET_BUS_RESET; */
result = SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET;
/*
* Wheeeee!!!
*/
mdelay(4 * 1000);
barrier();
if (flags & SCSI_RESET_SYNCHRONOUS) {
CMD_RESULT(cmd) = DID_BUS_BUSY << 16;
(*(cmd)->scsi_done)(cmd);
}
/* ha->reset_start = jiffies; */
break;
case ADAPTER_RESET:
default:
if (qla1280_verbose) {
printk(KERN_INFO
"scsi(%ld:%d:%d:%d): Issued an ADAPTER "
"RESET.\n", ha->host_no, bus, target, lun);
printk(KERN_INFO
"scsi(%ld:%d:%d:%d): I/O processing will "
"continue automatically.\n", ha->host_no, bus,
target, lun);
}
ha->flags.reset_active = TRUE;
/*
* We restarted all of the commands automatically, so the
* mid-level code can expect completions momentitarily.
*/
if (qla1280_abort_isp(ha) == 0)
result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET;
ha->flags.reset_active = FALSE;
}
if (ha->done_q_first)
qla1280_done(ha, &ha->done_q_first, &ha->done_q_last);
qla1280_restart_queues(ha);
ha->flags.in_reset = FALSE;
dprintk(1, "RESET returning %d\n", result);
LEAVE("qla1280_reset");
return result;
}
/**************************************************************************
* qla1280_biosparam
* Return the disk geometry for the given SCSI device.
**************************************************************************/
int
qla1280_biosparam(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int geom[])
{
int heads, sectors, cylinders;
heads = 64;
sectors = 32;
cylinders = (unsigned long)capacity / (heads * sectors);
if (cylinders > 1024) {
heads = 255;
sectors = 63;
cylinders = (unsigned long)capacity / (heads * sectors);
/* if (cylinders > 1023)
cylinders = 1023; */
}
geom[0] = heads;
geom[1] = sectors;
geom[2] = cylinders;
return 0;
}
/**************************************************************************
* qla1280_intr_handler
* Handles the H/W interrupt
**************************************************************************/
void
qla1280_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
{
struct scsi_qla_host *ha;
struct device_reg *reg;
u16 data;
ENTER_INTR ("qla1280_intr_handler");
ha = (struct scsi_qla_host *)dev_id;
spin_lock(ha->host->host_lock);
ha->isr_count++;
reg = ha->iobase;
WRT_REG_WORD(&reg->ictrl, 0); /* disable our interrupt. */
data = qla1280_debounce_register(&reg->istatus);
/* Check for pending interrupts. */
if (data & RISC_INT) {
qla1280_isr(ha, &ha->done_q_first, &ha->done_q_last);
} else {
/* spurious interrupts can happen legally */
dprintk(1, "scsi(%ld): Spurious interrupt - ignoring\n",
ha->host_no);
}
if (ha->done_q_first)
qla1280_done(ha, &ha->done_q_first, &ha->done_q_last);
spin_unlock(ha->host->host_lock);
/* enable our interrupt. */
WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT | ISP_EN_RISC));
LEAVE_INTR("qla1280_intr_handler");
}
/**************************************************************************
* qla1280_do_dpc
*
* Description:
* This routine is a task that is schedule by the interrupt handler
* to perform the background processing for interrupts. We put it
* on a task queue that is consumed whenever the scheduler runs; that's
* so you can do anything (i.e. put the process to sleep etc). In fact, the
* mid-level tries to sleep when it reaches the driver threshold
* "host->can_queue". This can cause a panic if we were in our interrupt
* code .
**************************************************************************/
void
qla1280_do_dpc(void *p)
{
struct scsi_qla_host *ha = (struct scsi_qla_host *) p;
unsigned long cpu_flags;
spin_lock_irqsave(ha->host->host_lock, cpu_flags);
if (ha->flags.isp_abort_needed)
qla1280_abort_isp(ha);
if (ha->flags.reset_marker)
qla1280_rst_aen(ha);
if (ha->done_q_first)
qla1280_done(ha, &ha->done_q_first, &ha->done_q_last);
spin_unlock_irqrestore(ha->host->host_lock, cpu_flags);
}
/**************************************************************************
* qla1280_slave_configure
*
* Description:
* Determines the queue depth for a given device. There are two ways
* a queue depth can be obtained for a tagged queueing device. One
* way is the default queue depth which is determined by whether
* If it is defined, then it is used
* as the default queue depth. Otherwise, we use either 4 or 8 as the
* default queue depth (dependent on the number of hardware SCBs).
**************************************************************************/
static int
qla1280_slave_configure(Scsi_Device * device)
{
struct scsi_qla_host *p = (struct scsi_qla_host *)device->host->hostdata;
int bus = device->channel;
int target = device->id;
if (qla1280_check_for_dead_scsi_bus(p, bus))
return 1;
if (device->tagged_supported &&
(p->bus_settings[bus].qtag_enables & (BIT_0 << target))) {
scsi_adjust_queue_depth(device, MSG_ORDERED_TAG,
p->bus_settings[bus].hiwat);
/* device->queue_depth = 20; */
printk(KERN_INFO "scsi(%li:%d:%d:%d): Enabled tagged queuing, "
"queue depth %d.\n", p->host_no, device->channel,
device->id, device->lun, device->queue_depth);
} else {
scsi_adjust_queue_depth(device, 0 /* TCQ off */, 3);
}
qla12160_get_target_parameters(p, bus, target, device->lun);
return 0;
}
/*
* Driver Support Routines
*/
/*
* qla1280_done
* Process completed commands.
*
* Input:
* ha = adapter block pointer.
* done_q_first = done queue first pointer.
* done_q_last = done queue last pointer.
*/
static void
qla1280_done(struct scsi_qla_host *ha, srb_t ** done_q_first,
srb_t ** done_q_last)
{
srb_t *sp;
scsi_lu_t *q;
int bus, target, lun;
Scsi_Cmnd *cmd;
ENTER("qla1280_done");
while (*done_q_first != NULL) {
/* remove command from done list */
sp = *done_q_first;
if (!(*done_q_first = sp->s_next))
*done_q_last = NULL;
else
(*done_q_first)->s_prev = NULL;
cmd = sp->cmd;
bus = SCSI_BUS_32(cmd);
target = SCSI_TCN_32(cmd);
lun = SCSI_LUN_32(cmd);
q = LU_Q(ha, bus, target, lun);
/* Decrement outstanding commands on device. */
if (q->q_outcnt)
q->q_outcnt--;
if (q->q_outcnt < ha->bus_settings[bus].hiwat) {
q->q_flag &= ~QLA1280_QBUSY;
}
q->io_cnt++;
if (sp->dir & BIT_5)
q->r_cnt++;
else
q->w_cnt++;
switch ((CMD_RESULT(cmd) >> 16)) {
case DID_RESET:
q->q_flag &= ~QLA1280_QRESET;
/* Issue marker command. */
qla1280_marker(ha, bus, target, 0, MK_SYNC_ID);
break;
case DID_ABORT:
sp->flags &= ~SRB_ABORT_PENDING;
sp->flags |= SRB_ABORTED;
if (sp->flags & SRB_TIMEOUT)
CMD_RESULT(sp->cmd) = DID_TIME_OUT << 16;
break;
default:
break;
}
/* 3.13 64 and 32 bit */
/* Release memory used for this I/O */
if (cmd->use_sg) {
dprintk(1, "S/G unmap_sg cmd=%p\n", cmd);
pci_unmap_sg(ha->pdev, cmd->request_buffer,
cmd->use_sg,
scsi_to_pci_dma_dir(cmd->sc_data_direction));
} else if (cmd->request_bufflen) {
/*dprintk(1, "No S/G unmap_single cmd=%x saved_dma_handle=%lx\n",
cmd, sp->saved_dma_handle); */
pci_unmap_single(ha->pdev, sp->saved_dma_handle,
cmd->request_bufflen,
scsi_to_pci_dma_dir(cmd->sc_data_direction));
}
/* Call the mid-level driver interrupt handler */
CMD_HANDLE(sp->cmd) = NULL;
ha->actthreads--;
(*(cmd)->scsi_done)(cmd);
qla1280_next(ha, q, bus);
}
LEAVE("qla1280_done");
}
/*
* Translates a ISP error to a Linux SCSI error
*/
static int
qla1280_return_status(sts_entry_t * sts, Scsi_Cmnd * cp)
{
int host_status = DID_ERROR;
#if DEBUG_QLA1280_INTR
static char *reason[] = {
"DID_OK",
"DID_NO_CONNECT",
"DID_BUS_BUSY",
"DID_TIME_OUT",
"DID_BAD_TARGET",
"DID_ABORT",
"DID_PARITY",
"DID_ERROR",
"DID_RESET",
"DID_BAD_INTR"
};
#endif /* DEBUG_QLA1280_INTR */
ENTER("qla1280_return_status");
#if DEBUG_QLA1280_INTR
/*
dprintk(1, "qla1280_return_status: compl status = 0x%04x\n",
sts->comp_status);
*/
#endif
switch (sts->comp_status) {
case CS_COMPLETE:
host_status = DID_OK;
break;
case CS_INCOMPLETE:
if (!(sts->state_flags & SF_GOT_BUS))
host_status = DID_NO_CONNECT;
else if (!(sts->state_flags & SF_GOT_TARGET))
host_status = DID_BAD_TARGET;
else if (!(sts->state_flags & SF_SENT_CDB))
host_status = DID_ERROR;
else if (!(sts->state_flags & SF_TRANSFERRED_DATA))
host_status = DID_ERROR;
else if (!(sts->state_flags & SF_GOT_STATUS))
host_status = DID_ERROR;
else if (!(sts->state_flags & SF_GOT_SENSE))
host_status = DID_ERROR;
break;
case CS_RESET:
host_status = DID_RESET;
break;
case CS_ABORTED:
host_status = DID_ABORT;
break;
case CS_TIMEOUT:
host_status = DID_TIME_OUT;
break;
case CS_DATA_OVERRUN:
dprintk(2, "Data overrun 0x%x\n", sts->residual_length);
dprintk(2, "qla1280_isr: response packet data\n");
qla1280_dump_buffer(2, (char *)sts, RESPONSE_ENTRY_SIZE);
host_status = DID_ERROR;
break;
case CS_DATA_UNDERRUN:
if ((cp->request_bufflen - sts->residual_length) <
cp->underflow) {
printk(KERN_WARNING
"scsi: Underflow detected - retrying "
"command.\n");
host_status = DID_ERROR;
} else
host_status = DID_OK;
break;
default:
host_status = DID_ERROR;
break;
}
#if DEBUG_QLA1280_INTR
dprintk(1, "qla1280 ISP status: host status (%s) scsi status %x\n",
reason[host_status], sts->scsi_status);
#endif
LEAVE("qla1280_return_status");
return (sts->scsi_status & 0xff) | (host_status << 16);
}
/*
* qla1280_done_q_put
* Place SRB command on done queue.
*
* Input:
* sp = srb pointer.
* done_q_first = done queue first pointer.
* done_q_last = done queue last pointer.
*/
static void
qla1280_done_q_put(srb_t * sp, srb_t ** done_q_first, srb_t ** done_q_last)
{
ENTER("qla1280_put_done_q");
/* Place block on done queue */
sp->s_next = NULL;
sp->s_prev = *done_q_last;
if (!*done_q_first)
*done_q_first = sp;
else
(*done_q_last)->s_next = sp;
*done_q_last = sp;
LEAVE("qla1280_put_done_q");
}
/*
* qla1280_next
* Retrieve and process next job in the queue.
*
* Input:
* ha = adapter block pointer.
* q = SCSI LU pointer.
* bus = SCSI bus number.
* SCSI_LU_Qlock must be already obtained and no other locks.
*
* Output:
* Releases SCSI_LU_Qupon exit.
*/
static void
qla1280_next(struct scsi_qla_host *ha, scsi_lu_t * q, int bus)
{
srb_t *sp;
int cnt, status;
ENTER("qla1280_next");
while (((sp = q->q_first) != NULL) && /* we have a queue pending */
/* device not busy/suspended */
!(q->q_flag & (QLA1280_QBUSY | QLA1280_QSUSP)) && !ha->flags.abort_isp_active) { /* not resetting the adapter */
/* Remove srb from SCSI LU queue. */
qla1280_removeq(q, sp);
dprintk(1, "starting request 0x%p<-(0x%p)\n", q, sp);
{
/* Set busy flag if reached high water mark. */
q->q_outcnt++;
if (q->q_outcnt >= ha->bus_settings[bus].hiwat)
q->q_flag |= QLA1280_QBUSY;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18)
if (ha->flags.enable_64bit_addressing)
status = qla1280_64bit_start_scsi(ha, sp);
else
#endif
status = qla1280_32bit_start_scsi(ha, sp);
if (status) { /* if couldn't start the request */
if (q->q_outcnt == 1) {
/* Wait for 30 sec for command to be accepted. */
for (cnt = 6000000; cnt; cnt--) {
#if QLA_64BIT_PTR
if (ha->flags.enable_64bit_addressing)
status =
qla1280_64bit_start_scsi(ha, sp);
else
#endif
status =
qla1280_32bit_start_scsi(ha, sp);
if (!status)
break;
/* Go check for pending interrupts. */
qla1280_poll(ha);
udelay(5); /* 10 */
}
if (!cnt) {
/* Set timeout status */
CMD_RESULT(sp->cmd) =
DID_TIME_OUT << 16;
#if WATCHDOGTIMER
/* Remove command from watchdog queue. */
if (sp->flags & SRB_WATCHDOG)
qla1280_timeout_remove
(ha, sp);
#endif
CMD_HANDLE(sp->cmd) = NULL;
/* Call the mid-level driver interrupt handler */
(*(sp->cmd)->scsi_done)(sp->cmd);
if (q->q_outcnt)
q->q_outcnt--;
}
} else { /* Place request back on top of device queue. */
qla1280_putq_t(q, sp);
if (q->q_outcnt)
q->q_outcnt--;
if (q->q_outcnt <
ha->bus_settings[bus].hiwat)
q->q_flag &= ~QLA1280_QBUSY;
break;
}
}
}
}
LEAVE("qla1280_next");
}
/*
* qla1280_putq_t
* Add the standard SCB job to the top of standard SCB commands.
*
* Input:
* q = SCSI LU pointer.
* sp = srb pointer.
* SCSI_LU_Qlock must be already obtained.
*/
static void
qla1280_putq_t(scsi_lu_t * q, srb_t * sp)
{
ENTER("qla1280_putq_t");
dprintk(1, "Adding to device q=0x%p<-(0x%p)sp\n", (void *) q,
(void *) sp);
sp->s_next = NULL;
if (!q->q_first) { /* If queue empty */
sp->s_prev = NULL;
q->q_first = sp;
q->q_last = sp;
} else {
sp->s_prev = q->q_last;
q->q_last->s_next = sp;
q->q_last = sp;
}
LEAVE("qla1280_putq_t");
}
/*
* qla1280_removeq
* Function used to remove a command block from the
* LU queue.
*
* Input:
* q = SCSI LU pointer.
* sp = srb pointer.
* SCSI_LU_Qlock must be already obtained.
*/
static void
qla1280_removeq(scsi_lu_t * q, srb_t * sp)
{
dprintk(1, "Removing from device_q (0x%p)->(0x%p)\n", q, sp);
if (sp->s_prev) {
if ((sp->s_prev->s_next = sp->s_next) != NULL)
sp->s_next->s_prev = sp->s_prev;
else
q->q_last = sp->s_prev;
} else if (!(q->q_first = sp->s_next))
q->q_last = NULL;
else
q->q_first->s_prev = NULL;
}
/*
* qla1280_mem_alloc
* Allocates adapter memory.
*
* Returns:
* 0 = success.
* 1 = failure.
*/
static int
qla1280_mem_alloc(struct scsi_qla_host *ha)
{
int status = 1;
dma_addr_t dma_handle;
ENTER("qla1280_mem_alloc");
/* 3.13 */
/* get consistent memory allocated for request and response rings */
ha->request_ring = pci_alloc_consistent(ha->pdev,
((REQUEST_ENTRY_CNT + 1) *
(sizeof(request_t))),
&dma_handle);
if (!ha->request_ring)
goto error;
ha->request_dma = dma_handle;
ha->response_ring = pci_alloc_consistent(ha->pdev,
((RESPONSE_ENTRY_CNT + 1) *
(sizeof(response_t))),
&dma_handle);
if (!ha->request_ring)
goto error;
ha->response_dma = dma_handle;
status = 0;
error:
if (status)
dprintk(2, "qla1280_mem_alloc: **** FAILED ****\n");
LEAVE("qla1280_mem_alloc");
return status;
}
/*
* qla1280_mem_free
* Frees adapter allocated memory.
*
* Input:
* ha = adapter block pointer.
*/
static void
qla1280_mem_free(struct scsi_qla_host *ha)
{
scsi_lu_t *q;
int bus, target, lun;
ENTER("qlc1280_mem_free");
if (ha) {
/* Free device queues. */
for (bus = 0; bus < MAX_BUSES; bus++) {
q = LU_Q(ha, bus, ha->bus_settings[bus].id, 0);
for (target = 0; target < MAX_TARGETS; target++)
for (lun = 0; lun < MAX_LUNS; lun++)
if (LU_Q(ha, bus, target, lun) != NULL
&& LU_Q(ha, bus, target, lun) != q)
kfree(LU_Q(ha, bus, target, lun));
kfree(q);
}
for (bus = 0; bus < MAX_EQ; bus++)
ha->dev[bus] = NULL;
}
/* 3.13 */
/* free consistent memory allocated for request and response rings */
if (ha->request_ring)
pci_free_consistent(ha->pdev,
((REQUEST_ENTRY_CNT + 1) *
(sizeof(request_t))),
ha->request_ring, ha->request_dma);
if (ha->response_ring)
pci_free_consistent(ha->pdev,
((RESPONSE_ENTRY_CNT + 1) *
(sizeof(response_t))),
ha->response_ring, ha->response_dma);
if (qla1280_buffer) {
free_page((unsigned long) qla1280_buffer);
qla1280_buffer = NULL;
}
LEAVE("qlc1280_mem_free");
}
/****************************************************************************/
/* QLogic ISP1280 Hardware Support Functions. */
/****************************************************************************/
/*
* qla2100_enable_intrs
* qla2100_disable_intrs
*
* Input:
* ha = adapter block pointer.
*
* Returns:
* None
*/
static inline void
qla1280_enable_intrs(struct scsi_qla_host *ha)
{
struct device_reg *reg;
reg = ha->iobase;
/* enable risc and host interrupts */
WRT_REG_WORD(&reg->ictrl, (ISP_EN_INT | ISP_EN_RISC));
ha->flags.ints_enabled = 1;
#if 0
printk("Enabling ints\n");
#endif
}
static inline void
qla1280_disable_intrs(struct scsi_qla_host *ha)
{
struct device_reg *reg;
reg = ha->iobase;
/* disable risc and host interrupts */
WRT_REG_WORD(&reg->ictrl, 0);
ha->flags.ints_enabled = 0;
#if 0
printk("Disabling ints\n");
#endif
}
/*
* qla1280_initialize_adapter
* Initialize board.
*
* Input:
* ha = adapter block pointer.
*
* Returns:
* 0 = success
*/
static int
qla1280_initialize_adapter(struct scsi_qla_host *ha)
{
struct device_reg *reg;
int status;
int bus;
ENTER("qla1280_initialize_adapter");
/* Clear adapter flags. */
ha->flags.online = FALSE;
ha->flags.isp_abort_needed = FALSE;
ha->flags.disable_host_adapter = FALSE;
ha->flags.reset_active = FALSE;
ha->flags.abort_isp_active = FALSE;
ha->flags.ints_enabled = FALSE;
dprintk(1, "Configure PCI space for adapter...\n");
reg = ha->iobase;
/* Insure mailbox registers are free. */
WRT_REG_WORD(&reg->semaphore, 0);
WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
WRT_REG_WORD(&reg->host_cmd, HC_CLR_HOST_INT);
/* If firmware needs to be loaded */
if (qla1280_verbose)
printk(KERN_INFO "scsi(%li): Determining if RISC is "
"loaded...\n", ha->host_no);
if (qla1280_isp_firmware(ha)) {
if (qla1280_verbose)
printk(KERN_INFO "scsi(%ld): Verifying chip...\n",
ha->host_no);
if (!(status = qla1280_chip_diag (ha))) {
if (qla1280_verbose)
printk(KERN_INFO "scsi(%ld): Setup chip...\n",
ha->host_no);
status = qla1280_setup_chip(ha);
}
} else {
printk(KERN_ERR "initialize: isp_firmware() failed!\n");
status = 1;
}
if (!status) {
/* Setup adapter based on NVRAM parameters. */
if (qla1280_verbose)
printk(KERN_INFO
"scsi(%ld): Configure NVRAM parameters...\n",
ha->host_no);
qla1280_nvram_config(ha);
if (!ha->flags.disable_host_adapter
&& !qla1280_init_rings(ha)) {
/* Issue SCSI reset. */
/* dg 03/13 if we can't reset twice then bus is dead */
for (bus = 0; bus < ha->ports; bus++) {
if (!ha->bus_settings[bus].disable_scsi_reset){
if (qla1280_bus_reset(ha, bus)) {
if (qla1280_bus_reset(ha, bus)) {
ha->bus_settings[bus].scsi_bus_dead = TRUE;
}
}
}
}
do {
/* Issue marker command. */
ha->flags.reset_marker = FALSE;
for (bus = 0; bus < ha->ports; bus++) {
ha->bus_settings[bus].reset_marker = FALSE;
qla1280_marker(ha, bus, 0, 0,
MK_SYNC_ALL);
}
} while (ha->flags.reset_marker);
ha->flags.online = TRUE;
/* Enable host adapter target mode. */
for (bus = 0; bus < ha->ports; bus++) {
if (!(status = qla1280_enable_tgt(ha, bus))) {
#if 0
int cnt;
for (cnt = 0; cnt < MAX_LUNS; cnt++) {
qla1280_enable_lun(ha, bus,
cnt);
qla1280_poll(ha);
}
#endif
} else
break;
}
} else
status = 1;
} else
printk(KERN_ERR "scsi(%li): initialize: pci probe failed!\n",
ha->host_no);
if (status)
dprintk(2, "qla1280_initialize_adapter: **** FAILED ****\n");
LEAVE("qla1280_initialize_adapter");
return status;
}
/*
* qla1280_enable_tgt
* Enable target mode.
*
* Input:
* ha = adapter block pointer.
* bus = SCSI bus number.
*
* Returns:
* 0 = success.
*/
static int
qla1280_enable_tgt(struct scsi_qla_host *ha, int bus)
{
int status = 0;
/* uint16_t mb[MAILBOX_REGISTER_COUNT]; */
dprintk(3, "qla1280_enable_tgt: entered\n");
/* Enable target mode. */
#if 0
mb[0] = MBC_ENABLE_TARGET_MODE;
mb[1] = BIT_15;
mb[2] = (uint16_t) (bus << 15);
status = qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
#endif
if (status)
dprintk(2, "qla1280_enable_tgt: **** FAILED ****\n");
else
dprintk(3, "qla1280_enable_tgt: exiting normally\n");
return status;
}
/*
* ISP Firmware Test
* Checks if present version of RISC firmware is older than
* driver firmware.
*
* Input:
* ha = adapter block pointer.
*
* Returns:
* 0 = firmware does not need to be loaded.
*/
static int
qla1280_isp_firmware(struct scsi_qla_host *ha)
{
nvram_t *nv = (nvram_t *) ha->response_ring;
uint16_t *wptr;
int status = 0; /* dg 2/27 always loads RISC */
int cnt;
uint8_t chksum;
uint16_t mb[MAILBOX_REGISTER_COUNT];
ENTER("qla1280_isp_firmware");
/* Verify valid NVRAM checksum. */
wptr = (uint16_t *) ha->response_ring;
dprintk(1, "qla1280_isp_firmware: Reading NVRAM\n");
chksum = 0;
for (cnt = 0; cnt < sizeof(nvram_t) / 2; cnt++) {
*wptr = qla1280_get_nvram_word (ha, cnt);
chksum += (uint8_t) * wptr;
chksum += (uint8_t) (*wptr >> 8);
wptr++;
}
dprintk(1, "qla1280_isp_firmware: Completed Reading NVRAM\n");
dprintk(3, "qla1280_isp_firmware: NVRAM Magic ID= %c %c %c\n",
(char *)nv->id[0], nv->id[1], nv->id[2]);
/* Bad NVRAM data, load RISC code. */
if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
nv->id[2] != 'P' || nv->id[3] != ' ' || nv->version < 1) {
printk(KERN_INFO "qla1280_isp_firmware: Bad checksum or magic "
"number or version in NVRAM.\n");
ha->flags.disable_risc_code_load = FALSE;
} else
ha->flags.disable_risc_code_load =
nv->cntr_flags_1.disable_loading_risc_code;
if (ha->flags.disable_risc_code_load) {
dprintk(3,
"qla1280_isp_firmware: Telling RISC to verify checksum "
"of loaded BIOS code.\n");
/* Verify checksum of loaded RISC code. */
mb[0] = MBC_VERIFY_CHECKSUM;
/* mb[1] = ql12_risc_code_addr01; */
mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
if (!
(status =
qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) {
/* Start firmware execution. */
dprintk(3, "qla1280_isp_firmware: Startng F/W "
"execution.\n");
mb[0] = MBC_EXECUTE_FIRMWARE;
/* mb[1] = ql12_risc_code_addr01; */
mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
} else
printk(KERN_INFO "qla1280: RISC checksum failed.\n");
} else {
dprintk(1, "qla1280: NVRAM configured to load RISC load.\n");
status = 1;
}
if (status)
dprintk(2, "qla1280_isp_firmware: **** Load RISC code ****\n");
LEAVE("qla1280_isp_firmware");
return status;
}
/*
* PCI configuration
* Setup device PCI configuration registers.
*
* Input:
* ha = adapter block pointer.
*
* Returns:
* 0 = success.
*/
static int
qla1280_pci_config(struct scsi_qla_host *ha)
{
#if MEMORY_MAPPED_IO
uint32_t page_offset, base;
uint32_t mmapbase;
#endif
uint16_t buf_wd;
int status = 1;
ENTER("qla1280_pci_config");
pci_set_master(ha->pdev);
/*
* Set Bus Master Enable, Memory Address Space Enable and
* reset any error bits, in the command register.
*/
pci_read_config_word (ha->pdev, PCI_COMMAND, &buf_wd);
#if MEMORY_MAPPED_IO
dprintk(1, "qla1280: MEMORY MAPPED IO is enabled.\n");
buf_wd |= PCI_COMMAND_MEMORY + PCI_COMMAND_IO;
#else
buf_wd |= PCI_COMMAND_IO;
#endif
pci_write_config_word (ha->pdev, PCI_COMMAND, buf_wd);
/*
* Reset expansion ROM address decode enable.
*/
pci_read_config_word (ha->pdev, PCI_ROM_ADDRESS, &buf_wd);
buf_wd &= ~PCI_ROM_ADDRESS_ENABLE;
pci_write_config_word (ha->pdev, PCI_ROM_ADDRESS, buf_wd);
ha->host->io_port = pci_resource_start(ha->pdev, 0);
ha->host->io_port &= PCI_BASE_ADDRESS_IO_MASK;
ha->iobase = (struct device_reg *) ha->host->io_port;
#if MEMORY_MAPPED_IO
/*
* Get memory mapped I/O address.
*/
pci_read_config_word (ha->pdev, PCI_BASE_ADDRESS_1, &mmapbase);
mmapbase &= PCI_BASE_ADDRESS_MEM_MASK;
/*
* Find proper memory chunk for memory map I/O reg.
*/
base = mmapbase & PAGE_MASK;
page_offset = mmapbase - base;
/*
* Get virtual address for I/O registers.
*/
ha->mmpbase = ioremap(base, page_offset + 256);
if (ha->mmpbase) {
ha->mmpbase += page_offset;
/* ha->iobase = ha->mmpbase; */
status = 0;
}
#else /* MEMORY_MAPPED_IO */
status = 0;
#endif /* MEMORY_MAPPED_IO */
LEAVE("qla1280_pci_config");
return status;
}
/*
* Chip diagnostics
* Test chip for proper operation.
*
* Input:
* ha = adapter block pointer.
*
* Returns:
* 0 = success.
*/
static int
qla1280_chip_diag(struct scsi_qla_host *ha)
{
uint16_t mb[MAILBOX_REGISTER_COUNT];
struct device_reg *reg = ha->iobase;
int status = 0;
int cnt;
uint16_t data;
dprintk(3, "qla1280_chip_diag: testing device at 0x%p \n", &reg->id_l);
/* Soft reset chip and wait for it to finish. */
WRT_REG_WORD(&reg->ictrl, ISP_RESET);
data = qla1280_debounce_register(&reg->ictrl);
/*
* This is *AWESOME*
*/
for (cnt = 6000000; cnt && data & ISP_RESET; cnt--) {
udelay(5);
data = RD_REG_WORD(&reg->ictrl);
}
if (cnt) {
/* Reset register not cleared by chip reset. */
dprintk(3,
"qla1280_chip_diag: reset register cleared by chip reset\n");
WRT_REG_WORD(&reg->cfg_1, 0);
/* Reset RISC and disable BIOS which
allows RISC to execute out of RAM. */
WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC);
WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
WRT_REG_WORD(&reg->host_cmd, HC_DISABLE_BIOS);
data = qla1280_debounce_register(&reg->mailbox0);
/*
* I *LOVE* this code!
*/
for (cnt = 6000000; cnt && data == MBS_BUSY; cnt--) {
udelay(5);
data = RD_REG_WORD(&reg->mailbox0);
}
if (cnt) {
/* Check product ID of chip */
dprintk(3,
"qla1280_chip_diag: Checking product ID of chip\n");
if (RD_REG_WORD(&reg->mailbox1) != PROD_ID_1 ||
(RD_REG_WORD(&reg->mailbox2) != PROD_ID_2 &&
RD_REG_WORD(&reg->mailbox2) != PROD_ID_2a) ||
RD_REG_WORD(&reg->mailbox3) != PROD_ID_3 ||
RD_REG_WORD(&reg->mailbox4) != PROD_ID_4) {
printk(KERN_INFO
"qla1280: Wrong product ID = 0x%x,0x%x,0x%x,"
"0x%x\n", RD_REG_WORD(&reg->mailbox1),
RD_REG_WORD(&reg->mailbox2),
RD_REG_WORD(&reg->mailbox3),
RD_REG_WORD(&reg->mailbox4));
status = 1;
} else {
/*
* Enable ints early!!!
*/
qla1280_enable_intrs(ha);
dprintk(1,
"qla1280_chip_diag: Checking mailboxes of chip\n");
/* Wrap Incoming Mailboxes Test. */
mb[0] = MBC_MAILBOX_REGISTER_TEST;
mb[1] = 0xAAAA;
mb[2] = 0x5555;
mb[3] = 0xAA55;
mb[4] = 0x55AA;
mb[5] = 0xA5A5;
mb[6] = 0x5A5A;
mb[7] = 0x2525;
if (!(status = qla1280_mailbox_command(ha,
BIT_7 |
BIT_6 |
BIT_5 |
BIT_4 |
BIT_3 |
BIT_2 |
BIT_1 |
BIT_0,
&mb
[0]))) {
if (mb[1] != 0xAAAA ||
mb[2] != 0x5555 ||
mb[3] != 0xAA55 ||
mb[4] != 0x55AA ||
mb[5] != 0xA5A5 ||
mb[6] != 0x5A5A ||
mb[7] != 0x2525)
status = 1;
if (status == 1)
printk(KERN_INFO
"qla1280: Failed mailbox check\n");
}
}
} else
status = 1;
} else
status = 1;
if (status)
dprintk(2, "qla1280_chip_diag: **** FAILED ****\n");
else
dprintk(3, "qla1280_chip_diag: exiting normally\n");
return status;
}
/*
* Setup chip
* Load and start RISC firmware.
*
* Input:
* ha = adapter block pointer.
*
* Returns:
* 0 = success.
*/
#define DUMP_IT_BACK 0 /* for debug of RISC loading */
static int
qla1280_setup_chip(struct scsi_qla_host *ha)
{
int status = 0;
uint16_t risc_address;
uint16_t *risc_code_address;
int risc_code_size;
uint16_t mb[MAILBOX_REGISTER_COUNT];
uint16_t cnt;
int num;
#if DUMP_IT_BACK
int i;
uint8_t *sp;
uint8_t *tbuf;
#ifdef QLA_64BIT_PTR
dma_addr_t p_tbuf;
#else
uint32_t p_tbuf;
#endif
#endif
ENTER("qla1280_setup_chip");
/* 3.13 */
#if DUMP_IT_BACK
/* get consistent memory allocated for setup_chip */
tbuf = pci_alloc_consistent(ha->pdev, 8000, &p_tbuf);
#endif
/* Load RISC code. */
risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
risc_code_size = (int) *ql1280_board_tbl[ha->devnum].fwlen;
dprintk(1, "qla1280_setup_chip: DMA RISC code (%i) words\n",
risc_code_size);
num = 0;
while (risc_code_size > 0 && !status) {
cnt = 2000 >> 1;
if (cnt > risc_code_size)
cnt = risc_code_size;
dprintk(1, "qla1280_setup_chip: loading risc @ =(0x%p),"
"%d,%d(0x%x)\n",
risc_code_address, cnt, num, risc_address);
memcpy(ha->request_ring, risc_code_address, (cnt << 1));
flush_cache_all();
mb[0] = MBC_LOAD_RAM;
mb[1] = risc_address;
mb[4] = cnt;
mb[3] = ha->request_dma & 0xffff;
mb[2] = (ha->request_dma >> 16) & 0xffff;
mb[7] = pci_dma_hi32(ha->request_dma) & 0xffff;
mb[6] = pci_dma_hi32(ha->request_dma) >> 16;
dprintk(1, "qla1280_setup_chip: op=%d 0x%p = 0x%4x,0x%4x,"
"0x%4x,0x%4x\n",
mb[0], ha->request_dma, mb[6], mb[7], mb[2], mb[3]);
if ((status = qla1280_mailbox_command(ha, BIT_4 | BIT_3 |
BIT_2 | BIT_1 | BIT_0,
&mb[0]))) {
printk(KERN_ERR
"Failed to load partial segment of f/w\n");
break;
}
#if DUMP_IT_BACK
mb[0] = MBC_READ_RAM_WORD;
mb[1] = risc_address;
mb[4] = cnt;
mb[3] = p_tbuf & 0xffff;
mb[2] = (p_tbuf >> 16) & 0xffff;
mb[7] = pci_dma_hi32(p_tbuf) & 0xffff;
mb[6] = pci_dma_hi32(p_tbuf) >> 16;
if ((status = qla1280_mailbox_command(ha,
BIT_4 | BIT_3 | BIT_2 |
BIT_1 | BIT_0,
&mb[0]))) {
printk(KERN_ERR
"Failed to dump partial segment of f/w\n");
break;
}
sp = (uint8_t *)ha->request_ring;
for (i = 0; i < (cnt << 1); i++) {
if (tbuf[i] != sp[i]) {
printk(KERN_ERR "qla1280_setup_chip: FW "
"compare error @ byte(0x%x) loop#=%x\n",
i, num);
printk(KERN_ERR "setup_chip: FWbyte=%x "
"FWfromChip=%x\n", sp[i], tbuf[i]);
/*break; */
}
}
#endif
risc_address += cnt;
risc_code_size = risc_code_size - cnt;
risc_code_address = risc_code_address + cnt;
num++;
}
/* Verify checksum of loaded RISC code. */
if (!status) {
dprintk(1, "qla1280_setup_chip: Verifying checksum of "
"loaded RISC code.\n");
mb[0] = MBC_VERIFY_CHECKSUM;
/* mb[1] = ql12_risc_code_addr01; */
mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
if (!(status =
qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) {
/* Start firmware execution. */
dprintk(1,
"qla1280_setup_chip: start firmware running.\n");
mb[0] = MBC_EXECUTE_FIRMWARE;
mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
} else
printk(KERN_ERR
"qla1280_setup_chip: Failed checksum.\n");
}
/* 3.13 */
#if DUMP_IT_BACK
/* free consistent memory allocated for setup_chip */
pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf);
#endif
if (status)
dprintk(2, "qla1280_setup_chip: **** FAILED ****\n");
LEAVE("qla1280_setup_chip");
return status;
}
/*
* Initialize rings
*
* Input:
* ha = adapter block pointer.
* ha->request_ring = request ring virtual address
* ha->response_ring = response ring virtual address
* ha->request_dma = request ring physical address
* ha->response_dma = response ring physical address
*
* Returns:
* 0 = success.
*/
static int
qla1280_init_rings(struct scsi_qla_host *ha)
{
uint16_t mb[MAILBOX_REGISTER_COUNT];
int status = 0;
int cnt;
ENTER("qla1280_init_rings");
/* Clear outstanding commands array. */
for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++)
ha->outstanding_cmds[cnt] = 0;
/* Initialize request queue. */
ha->request_ring_ptr = ha->request_ring;
ha->req_ring_index = 0;
ha->req_q_cnt = REQUEST_ENTRY_CNT;
/* mb[0] = MBC_INIT_REQUEST_QUEUE; */
mb[0] = MBC_INIT_REQUEST_QUEUE_A64;
mb[1] = REQUEST_ENTRY_CNT;
mb[3] = ha->request_dma & 0xffff;
mb[2] = (ha->request_dma >> 16) & 0xffff;
mb[4] = 0;
mb[7] = pci_dma_hi32(ha->request_dma) & 0xffff;
mb[6] = pci_dma_hi32(ha->request_dma) >> 16;
if (!(status = qla1280_mailbox_command(ha, BIT_7 | BIT_6 | BIT_4 |
BIT_3 | BIT_2 | BIT_1 | BIT_0,
&mb[0]))) {
/* Initialize response queue. */
ha->response_ring_ptr = ha->response_ring;
ha->rsp_ring_index = 0;
/* mb[0] = MBC_INIT_RESPONSE_QUEUE; */
mb[0] = MBC_INIT_RESPONSE_QUEUE_A64;
mb[1] = RESPONSE_ENTRY_CNT;
mb[3] = ha->response_dma & 0xffff;
mb[2] = (ha->response_dma >> 16) & 0xffff;
mb[5] = 0;
mb[7] = pci_dma_hi32(ha->response_dma) & 0xffff;
mb[6] = pci_dma_hi32(ha->response_dma) >> 16;
status = qla1280_mailbox_command(ha, BIT_7 | BIT_6 | BIT_5 |
BIT_3 | BIT_2 | BIT_1 | BIT_0,
&mb[0]);
}
if (status)
dprintk(2, "qla1280_init_rings: **** FAILED ****\n");
LEAVE("qla1280_init_rings");
return status;
}
/*
* NVRAM configuration.
*
* Input:
* ha = adapter block pointer.
* ha->request_ring = request ring virtual address
*
* Output:
* host adapters parameters in host adapter block
*
* Returns:
* 0 = success.
*/
static int
qla1280_nvram_config(struct scsi_qla_host *ha)
{
struct device_reg *reg = ha->iobase;
nvram_t *nv = (nvram_t *)ha->response_ring;
int status = 0;
int cnt;
int bus, target, lun;
uint16_t *wptr;
uint16_t mb[MAILBOX_REGISTER_COUNT];
uint8_t chksum;
int nvsize;
#if DEBUG_PRINT_NVRAM
int saved_print_status = ql_debug_print;
#endif
ENTER("qla1280_nvram_config");
/* Verify valid NVRAM checksum. */
#if USE_NVRAM_DEFAULTS
chksum = 1;
#else
wptr = (uint16_t *) ha->response_ring;
chksum = 0;
if (ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160 ||
ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP10160)
nvsize = sizeof(nvram160_t) / 2;
else
nvsize = sizeof(nvram_t) / 2;
for (cnt = 0; cnt < nvsize; cnt++) {
*wptr = qla1280_get_nvram_word(ha, cnt);
chksum += (uint8_t) * wptr;
chksum += (uint8_t) (*wptr >> 8);
wptr++;
}
#endif
/* Bad NVRAM data, set defaults parameters. */
if (chksum || nv->id[0] != 'I' || nv->id[1] != 'S' ||
nv->id[2] != 'P' || nv->id[3] != ' ' || nv->version < 1) {
#if USE_NVRAM_DEFAULTS
dprintk(1, "Using defaults for NVRAM\n");
#else
dprintk(1, "Using defaults for NVRAM: \n");
dprintk(1, "checksum=0x%x, Id=%c, version=0x%x\n",
chksum, nv->id[0], nv->version);
memset(ha->response_ring, 0, sizeof(nvram_t));
#endif
/* nv->cntr_flags_1.disable_loading_risc_code = 1; */
nv->firmware_feature.w = BIT_0;
nv->termination.f.scsi_bus_0_control = 3;
nv->termination.f.scsi_bus_1_control = 3;
nv->termination.f.auto_term_support = 1;
for (bus = 0; bus < MAX_BUSES; bus++) {
nv->bus[bus].config_1.initiator_id = 7;
nv->bus[bus].bus_reset_delay = 5;
nv->bus[bus].config_2.async_data_setup_time = 9;
nv->bus[bus].config_2.req_ack_active_negation = 1;
nv->bus[bus].config_2.data_line_active_negation = 1;
nv->bus[bus].selection_timeout = 250;
nv->bus[bus].max_queue_depth = 256;
for (target = 0; target < MAX_TARGETS; target++) {
nv->bus[bus].target[target].parameter.f.
auto_request_sense = 1;
nv->bus[bus].target[target].parameter.f.
disconnect_allowed = 1;
nv->bus[bus].target[target].parameter.f.
tag_queuing = 1;
nv->bus[bus].target[target].flags.
device_enable = 1;
}
}
#if USE_NVRAM_DEFAULTS
status = 0;
#else
status = 1;
#endif
} else {
/* Always force AUTO sense for LINUX SCSI */
for (bus = 0; bus < MAX_BUSES; bus++)
for (target = 0; target < MAX_TARGETS; target++) {
nv->bus[bus].target[target].parameter.f.
auto_request_sense = 1;
}
}
#if DEBUG_PRINT_NVRAM
ql_debug_print = 1;
#endif
dprintk(1, "qla1280 : initiator scsi id bus[0]=%d\n",
nv->bus[0].config_1.initiator_id);
dprintk(1, "qla1280 : initiator scsi id bus[1]=%d\n",
nv->bus[1].config_1.initiator_id);
dprintk(1, "qla1280 : bus reset delay[0]=%d\n",
nv->bus[0].bus_reset_delay);
dprintk(1, "qla1280 : bus reset delay[1]=%d\n",
nv->bus[1].bus_reset_delay);
dprintk(1, "qla1280 : retry count[0]=%d\n", nv->bus[0].retry_count);
dprintk(1, "qla1280 : retry delay[0]=%d\n", nv->bus[0].retry_delay);
dprintk(1, "qla1280 : retry count[1]=%d\n", nv->bus[1].retry_count);
dprintk(1, "qla1280 : retry delay[1]=%d\n", nv->bus[1].retry_delay);
dprintk(1, "qla1280 : async data setup time[0]=%d\n",
nv->bus[0].config_2.async_data_setup_time);
dprintk(1, "qla1280 : async data setup time[1]=%d\n",
nv->bus[1].config_2.async_data_setup_time);
dprintk(1, "qla1280 : req/ack active negation[0]=%d\n",
nv->bus[0].config_2.req_ack_active_negation);
dprintk(1, "qla1280 : req/ack active negation[1]=%d\n",
nv->bus[1].config_2.req_ack_active_negation);
dprintk(1, "qla1280 : data line active negation[0]=%d\n",
nv->bus[0].config_2.data_line_active_negation);
dprintk(1, "qla1280 : data line active negation[1]=%d\n",
nv->bus[1].config_2.data_line_active_negation);
dprintk(1, "qla1280 : disable loading risc code=%d\n",
nv->cntr_flags_1.disable_loading_risc_code);
dprintk(1, "qla1280 : enable 64bit addressing=%d\n",
nv->cntr_flags_1.enable_64bit_addressing);
dprintk(1, "qla1280 : selection timeout limit[0]=%d\n",
nv->bus[0].selection_timeout);
dprintk(1, "qla1280 : selection timeout limit[1]=%d\n",
nv->bus[1].selection_timeout);
dprintk(1, "qla1280 : max queue depth[0]=%d\n",
nv->bus[0].max_queue_depth);
dprintk(1, "qla1280 : max queue depth[1]=%d\n",
nv->bus[1].max_queue_depth);
/* Disable RISC load of firmware. */
ha->flags.disable_risc_code_load =
nv->cntr_flags_1.disable_loading_risc_code;
#ifdef QLA_64BIT_PTR
/* Enable 64bit addressing for OS/System combination supporting it */
/* actual NVRAM bit is: nv->cntr_flags_1.enable_64bit_addressing */
/* but we will ignore it and use BITS_PER_LONG macro to setup for */
/* 64 or 32 bit access of host memory in all x86/ia-64/Alpha systems */
ha->flags.enable_64bit_addressing = 1;
#else
ha->flags.enable_64bit_addressing = 0;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18)
if (ha->flags.enable_64bit_addressing) {
printk(KERN_INFO "scsi(%li): 64 Bit PCI Addressing Enabled\n",
ha->host_no);
pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL);
}
#endif
/* Set ISP hardware DMA burst */
mb[0] = nv->isp_config.c;
WRT_REG_WORD(&reg->cfg_1, mb[0]);
/* Set SCSI termination. */
WRT_REG_WORD(&reg->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
WRT_REG_WORD(&reg->gpio_data, mb[0]);
/* ISP parameter word. */
mb[0] = MBC_SET_SYSTEM_PARAMETER;
mb[1] = nv->isp_parameter;
status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
/* Firmware feature word. */
mb[0] = MBC_SET_FIRMWARE_FEATURES;
mb[1] = nv->firmware_feature.w & (BIT_1 | BIT_0);
status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
/* Retry count and delay. */
mb[0] = MBC_SET_RETRY_COUNT;
mb[1] = nv->bus[0].retry_count;
mb[2] = nv->bus[0].retry_delay;
mb[6] = nv->bus[1].retry_count;
mb[7] = nv->bus[1].retry_delay;
status |=
qla1280_mailbox_command(ha, BIT_7 | BIT_6 | BIT_2 | BIT_1 | BIT_0,
&mb[0]);
/* ASYNC data setup time. */
mb[0] = MBC_SET_ASYNC_DATA_SETUP;
mb[1] = nv->bus[0].config_2.async_data_setup_time;
mb[2] = nv->bus[1].config_2.async_data_setup_time;
status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
/* Active negation states. */
mb[0] = MBC_SET_ACTIVE_NEGATION;
mb[1] = 0;
if (nv->bus[0].config_2.req_ack_active_negation)
mb[1] |= BIT_5;
if (nv->bus[0].config_2.data_line_active_negation)
mb[1] |= BIT_4;
mb[2] = 0;
if (nv->bus[1].config_2.req_ack_active_negation)
mb[2] |= BIT_5;
if (nv->bus[1].config_2.data_line_active_negation)
mb[2] |= BIT_4;
status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
/* Selection timeout. */
mb[0] = MBC_SET_SELECTION_TIMEOUT;
mb[1] = nv->bus[0].selection_timeout;
mb[2] = nv->bus[1].selection_timeout;
status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
for (bus = 0; bus < ha->ports; bus++) {
/* SCSI Reset Disable. */
ha->bus_settings[bus].disable_scsi_reset =
nv->bus[bus].config_1.scsi_reset_disable;
/* Initiator ID. */
ha->bus_settings[bus].id = nv->bus[bus].config_1.initiator_id;
mb[0] = MBC_SET_INITIATOR_ID;
mb[1] = bus ? ha->bus_settings[bus].id | BIT_7 :
ha->bus_settings[bus].id;
status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
/* Reset Delay. */
ha->bus_settings[bus].bus_reset_delay =
nv->bus[bus].bus_reset_delay;
/* Command queue depth per device. */
ha->bus_settings[bus].hiwat = nv->bus[bus].max_queue_depth - 1;
/* Set target parameters. */
for (target = 0; target < MAX_TARGETS; target++) {
uint8_t mr = BIT_3 | BIT_2 | BIT_1 | BIT_0;
/* Set Target Parameters. */
mb[0] = MBC_SET_TARGET_PARAMETERS;
mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
mb[1] <<= 8;
mb[2] = nv->bus[bus].target[target].parameter.c << 8;
mb[2] |= TP_AUTO_REQUEST_SENSE;
mb[2] &= ~TP_STOP_QUEUE;
mb[3] =
nv->bus[bus].target[target].flags.sync_offset << 8;
mb[3] |= nv->bus[bus].target[target].sync_period;
if (ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP12160 ||
ha->device_id == PCI_DEVICE_ID_QLOGIC_ISP10160) {
nvram160_t *nv2 = (nvram160_t *) nv;
mb[2] |=
nv2->bus[bus].target[target].flags.
enable_ppr << 5;
mb[6] =
nv2->bus[bus].target[target].flags.
ppr_options << 8;
mb[6] |=
nv2->bus[bus].target[target].flags.
ppr_bus_width;
mr |= BIT_6;
}
status = qla1280_mailbox_command(ha, mr, &mb[0]);
/* Save Tag queuing enable flag. */
mb[0] = BIT_0 << target;
if (nv->bus[bus].target[target].parameter.f.tag_queuing)
ha->bus_settings[bus].qtag_enables |= mb[0];
/* Save Device enable flag. */
if (nv->bus[bus].target[target].flags.device_enable)
ha->bus_settings[bus].device_enables |= mb[0];
/* Save LUN disable flag. */
if (nv->bus[bus].target[target].flags.lun_disable)
ha->bus_settings[bus].lun_disables |= mb[0];
/* Set Device Queue Parameters. */
for (lun = 0; lun < MAX_LUNS; lun++) {
mb[0] = MBC_SET_DEVICE_QUEUE;
mb[1] = (uint16_t)(bus ? target | BIT_7 : target);
mb[1] = mb[1] << 8 | lun;
mb[2] = nv->bus[bus].max_queue_depth;
mb[3] = nv->bus[bus].target[target].execution_throttle;
status |=
qla1280_mailbox_command(ha,
BIT_3 | BIT_2 |
BIT_1 | BIT_0,
&mb[0]);
}
}
}
#if DEBUG_PRINT_NVRAM
ql_debug_print = saved_print_status;
#endif
if (status)
dprintk(2, "qla1280_nvram_config: **** FAILED ****\n");
LEAVE("qla1280_nvram_config");
return status;
}
/*
* Get NVRAM data word
* Calculates word position in NVRAM and calls request routine to
* get the word from NVRAM.
*
* Input:
* ha = adapter block pointer.
* address = NVRAM word address.
*
* Returns:
* data word.
*/
static uint16_t
qla1280_get_nvram_word(struct scsi_qla_host *ha, uint32_t address)
{
uint32_t nv_cmd;
uint16_t data;
#ifdef QL_DEBUG_ROUTINES
int saved_print_status = ql_debug_print;
#endif
nv_cmd = address << 16;
nv_cmd |= NV_READ_OP;
#ifdef QL_DEBUG_ROUTINES
ql_debug_print = FALSE;
#endif
data = qla1280_nvram_request(ha, nv_cmd);
#ifdef QL_DEBUG_ROUTINES
ql_debug_print = saved_print_status;
#endif
dprintk(4,
"qla1280_get_nvram_word: exiting normally NVRAM data = 0x%x",
data);
return data;
}
/*
* NVRAM request
* Sends read command to NVRAM and gets data from NVRAM.
*
* Input:
* ha = adapter block pointer.
* nv_cmd = Bit 26 = start bit
* Bit 25, 24 = opcode
* Bit 23-16 = address
* Bit 15-0 = write data
*
* Returns:
* data word.
*/
static uint16_t
qla1280_nvram_request(struct scsi_qla_host *ha, uint32_t nv_cmd)
{
struct device_reg *reg = ha->iobase;
int cnt;
uint16_t data = 0;
uint16_t reg_data;
/* Send command to NVRAM. */
nv_cmd <<= 5;
for (cnt = 0; cnt < 11; cnt++) {
if (nv_cmd & BIT_31)
qla1280_nv_write(ha, NV_DATA_OUT);
else
qla1280_nv_write(ha, 0);
nv_cmd <<= 1;
}
/* Read data from NVRAM. */
for (cnt = 0; cnt < 16; cnt++) {
WRT_REG_WORD(&reg->nvram, (NV_SELECT | NV_CLOCK));
NVRAM_DELAY();
data <<= 1;
reg_data = RD_REG_WORD(&reg->nvram);
if (reg_data & NV_DATA_IN)
data |= BIT_0;
WRT_REG_WORD(&reg->nvram, NV_SELECT);
NVRAM_DELAY();
}
/* Deselect chip. */
WRT_REG_WORD(&reg->nvram, NV_DESELECT);
NVRAM_DELAY();
return data;
}
static void
qla1280_nv_write(struct scsi_qla_host *ha, uint16_t data)
{
struct device_reg *reg = ha->iobase;
WRT_REG_WORD(&reg->nvram, data | NV_SELECT);
NVRAM_DELAY();
WRT_REG_WORD(&reg->nvram, data | NV_SELECT | NV_CLOCK);
NVRAM_DELAY();
WRT_REG_WORD(&reg->nvram, data | NV_SELECT);
NVRAM_DELAY();
}
/*
* Mailbox Command
* Issue mailbox command and waits for completion.
*
* Input:
* ha = adapter block pointer.
* mr = mailbox registers to load.
* mb = data pointer for mailbox registers.
*
* Output:
* mb[MAILBOX_REGISTER_COUNT] = returned mailbox data.
*
* Returns:
* 0 = success
*/
static int
qla1280_mailbox_command(struct scsi_qla_host *ha, uint8_t mr, uint16_t * mb)
{
struct device_reg *reg = ha->iobase;
#if 0
srb_t *done_q_first = 0;
srb_t *done_q_last = 0;
#endif
int status = 0;
int cnt;
uint16_t *optr, *iptr;
uint16_t data;
ENTER("qla1280_mailbox_command");
ha->flags.mbox_busy = TRUE;
if (!ha->flags.ints_enabled)
printk(KERN_DEBUG
"Running qla1280_mailbox_command() with interrupts "
"disabled!\n");
/*
* We really should start out by verifying that the mailbox is available
* before starting sending the command data
*/
/* Load mailbox registers. */
optr = (uint16_t *) &reg->mailbox0;
iptr = mb;
for (cnt = 0; cnt < MAILBOX_REGISTER_COUNT; cnt++) {
if (mr & BIT_0) {
WRT_REG_WORD(optr, (*iptr));
}
mr >>= 1;
optr++;
iptr++;
}
/* Issue set host interrupt command. */
ha->flags.mbox_int = FALSE;
ha->flags.mbox_busy = FALSE;
WRT_REG_WORD(&reg->host_cmd, HC_SET_HOST_INT);
data = qla1280_debounce_register(&reg->istatus);
/*
* This is insane - instead of looping to wait for the interrupt
* to appear and run the handler (this is insane!!), use a waitqueue
* and go to sleep.
*
* We are never called here from interrupt context anyway! /Jes
*/
/* Wait for 30 seconds for command to finish. */
for (cnt = 30000000; cnt > 0 && !ha->flags.mbox_int; cnt--) {
/* Check for pending interrupts. */
#if 0
if (data & RISC_INT) {
qla1280_isr(ha, &done_q_first, &done_q_last);
} else
#endif
udelay(1);
data = RD_REG_WORD(&reg->istatus);
}
/* Check for mailbox command timeout. */
if (!cnt) {
printk(KERN_WARNING
"qla1280_mailbox_command: **** Command Timeout, "
"mailbox0 = 0x%x****\n", mb[0]);
ha->flags.isp_abort_needed = TRUE;
status = 1;
} else if (ha->mailbox_out[0] != MBS_CMD_CMP)
status = 1;
/* Load return mailbox registers. */
optr = mb;
iptr = (uint16_t *) &ha->mailbox_out[0];
mr = MAILBOX_REGISTER_COUNT;
memcpy(optr, iptr, MAILBOX_REGISTER_COUNT * sizeof(uint16_t));
#if 0
/* Go check for any response interrupts pending. */
qla1280_isr(ha, &done_q_first, &done_q_last);
#endif
if (ha->flags.isp_abort_needed)
qla1280_abort_isp(ha);
if (ha->flags.reset_marker)
qla1280_rst_aen(ha);
#if 0
if (done_q_first)
qla1280_done (ha, &done_q_first, &done_q_last);
#endif
if (status)
dprintk(2,
"qla1280_mailbox_command: **** FAILED, mailbox0 = 0x%x "
"****n", mb[0]);
LEAVE("qla1280_mailbox_command");
return status;
}
/*
* qla1280_poll
* Polls ISP for interrupts.
*
* Input:
* ha = adapter block pointer.
*/
static void
qla1280_poll(struct scsi_qla_host *ha)
{
struct device_reg *reg = ha->iobase;
uint16_t data;
srb_t *done_q_first = 0;
srb_t *done_q_last = 0;
/* ENTER("qla1280_poll"); */
/* Check for pending interrupts. */
data = RD_REG_WORD(&reg->istatus);
if (data & RISC_INT)
qla1280_isr(ha, &done_q_first, &done_q_last);
if (!ha->flags.mbox_busy) {
if (ha->flags.isp_abort_needed)
qla1280_abort_isp(ha);
if (ha->flags.reset_marker)
qla1280_rst_aen(ha);
}
if (done_q_first)
qla1280_done(ha, &done_q_first, &done_q_last);
/* LEAVE("qla1280_poll"); */
}
/*
* qla1280_bus_reset
* Issue SCSI bus reset.
*
* Input:
* ha = adapter block pointer.
* bus = SCSI bus number.
*
* Returns:
* 0 = success
*/
static int
qla1280_bus_reset(struct scsi_qla_host *ha, int bus)
{
uint16_t mb[MAILBOX_REGISTER_COUNT];
int status;
dprintk(3, "qla1280_bus_reset: entered\n");
if (qla1280_verbose)
printk(KERN_INFO "scsi(%li): Resetting SCSI BUS (%i)\n",
ha->host_no, bus);
mb[0] = MBC_BUS_RESET;
mb[1] = ha->bus_settings[bus].bus_reset_delay;
mb[2] = (uint16_t) bus;
status = qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
if (status) {
if (ha->bus_settings[bus].failed_reset_count > 2) /* dg - 03/13/99 */
ha->bus_settings[bus].scsi_bus_dead = TRUE;
ha->bus_settings[bus].failed_reset_count++;
} else {
/*
* Eeeeep! This is evil! /Jes
*/
#if 0
mdelay(4000);
#else
schedule_timeout(4 * HZ);
#endif
ha->bus_settings[bus].scsi_bus_dead = FALSE; /* dg - 03/13/99 */
ha->bus_settings[bus].failed_reset_count = 0;
/* Issue marker command. */
qla1280_marker(ha, bus, 0, 0, MK_SYNC_ALL);
}
if (status)
dprintk(2, "qla1280_bus_reset: **** FAILED ****\n");
else
dprintk(3, "qla1280_bus_reset: exiting normally\n");
return status;
}
/*
* qla1280_device_reset
* Issue bus device reset message to the target.
*
* Input:
* ha = adapter block pointer.
* bus = SCSI BUS number.
* target = SCSI ID.
*
* Returns:
* 0 = success
*/
static int
qla1280_device_reset(struct scsi_qla_host *ha, int bus, int target)
{
uint16_t mb[MAILBOX_REGISTER_COUNT];
int status;
ENTER("qla1280_device_reset");
mb[0] = MBC_ABORT_TARGET;
mb[1] = (bus ? (target | BIT_7) : target) << 8;
mb[2] = 1;
status = qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
/* Issue marker command. */
qla1280_marker(ha, bus, target, 0, MK_SYNC_ID);
if (status)
dprintk(2, "qla1280_device_reset: **** FAILED ****\n");
LEAVE("qla1280_device_reset");
return status;
}
/*
* qla1280_abort_device
* Issue an abort message to the device
*
* Input:
* ha = adapter block pointer.
* bus = SCSI BUS.
* target = SCSI ID.
* lun = SCSI LUN.
*
* Returns:
* 0 = success
*/
static int
qla1280_abort_device(struct scsi_qla_host *ha, int bus, int target, int lun)
{
uint16_t mb[MAILBOX_REGISTER_COUNT];
int status;
ENTER("qla1280_abort_device");
mb[0] = MBC_ABORT_DEVICE;
mb[1] = (bus ? target | BIT_7 : target) << 8 | lun;
status = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
/* Issue marker command. */
qla1280_marker(ha, bus, target, lun, MK_SYNC_ID_LUN);
if (status)
dprintk(2, "qla1280_abort_device: **** FAILED ****\n");
LEAVE("qla1280_abort_device");
return status;
}
/*
* qla1280_abort_command
* Abort command aborts a specified IOCB.
*
* Input:
* ha = adapter block pointer.
* sp = SB structure pointer.
*
* Returns:
* 0 = success
*/
static int
qla1280_abort_command(struct scsi_qla_host *ha, srb_t * sp)
{
uint16_t mb[MAILBOX_REGISTER_COUNT];
unsigned int bus, target, lun;
uint32_t handle;
int status;
ENTER("qla1280_abort_command");
/* Locate handle number. */
for (handle = 0; handle < MAX_OUTSTANDING_COMMANDS; handle++)
if (ha->outstanding_cmds[handle] == sp)
break;
bus = SCSI_BUS_32(sp->cmd);
target = SCSI_TCN_32(sp->cmd);
lun = SCSI_LUN_32(sp->cmd);
mb[0] = MBC_ABORT_COMMAND;
mb[1] = (bus ? target | BIT_7 : target) << 8 | lun;
mb[2] = handle >> 16;
mb[3] = handle & 0xffff;
status =
qla1280_mailbox_command(ha, BIT_3 | BIT_2 | BIT_1 | BIT_0, &mb[0]);
if (status)
dprintk(2, "qla1280_abort_command: **** FAILED ****\n");
sp->flags |= SRB_ABORT_PENDING;
LEAVE("qla1280_abort_command");
return status;
}
/*
* qla1280_reset_adapter
* Reset adapter.
*
* Input:
* ha = adapter block pointer.
*/
static void
qla1280_reset_adapter(struct scsi_qla_host *ha)
{
struct device_reg *reg = ha->iobase;
ENTER("qla1280_reset_adapter");
/* Disable ISP chip */
ha->flags.online = FALSE;
WRT_REG_WORD(&reg->ictrl, ISP_RESET);
WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC);
WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
WRT_REG_WORD(&reg->host_cmd, HC_DISABLE_BIOS);
LEAVE("qla1280_reset_adapter");
}
/*
* Issue marker command.
* Function issues marker IOCB.
*
* Input:
* ha = adapter block pointer.
* bus = SCSI BUS number
* id = SCSI ID
* lun = SCSI LUN
* type = marker modifier
*/
static void
qla1280_marker(struct scsi_qla_host *ha, int bus, int id, int lun, u8 type)
{
mrk_entry_t *pkt;
ENTER("qla1280_marker");
/* Get request packet. */
if ((pkt = (mrk_entry_t *) qla1280_req_pkt(ha))) {
pkt->entry_type = MARKER_TYPE;
pkt->lun = (uint8_t) lun;
pkt->target = (uint8_t) (bus ? (id | BIT_7) : id);
pkt->modifier = type;
/* Issue command to ISP */
qla1280_isp_cmd(ha);
}
LEAVE("qla1280_marker");
}
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,18)
/*
* qla1280_64bit_start_scsi
* The start SCSI is responsible for building request packets on
* request ring and modifying ISP input pointer.
*
* Input:
* ha = adapter block pointer.
* sp = SB structure pointer.
*
* Returns:
* 0 = success, was able to issue command.
*/
static int
qla1280_64bit_start_scsi(struct scsi_qla_host *ha, srb_t * sp)
{
struct device_reg *reg = ha->iobase;
Scsi_Cmnd *cmd = sp->cmd;
cmd_a64_entry_t *pkt;
struct scatterlist *sg = NULL;
u32 *dword_ptr;
dma_addr_t dma_handle;
int status = 0;
int cnt;
int req_cnt;
u16 seg_cnt;
ENTER("qla1280_64bit_start_scsi:");
dprintk(1, "64bit_start: cmd=%p sp=%p CDB=%x\n", cmd, sp,
cmd->cmnd[0]);
/* Calculate number of entries and segments required. */
req_cnt = 1;
if (cmd->use_sg) { /* 3.13 64 bit */
sg = (struct scatterlist *) cmd->request_buffer;
seg_cnt = pci_map_sg (ha->pdev, sg, cmd->use_sg,
scsi_to_pci_dma_dir(cmd->sc_data_direction));
if (seg_cnt > 2) {
req_cnt += (seg_cnt - 2) / 5;
if ((seg_cnt - 2) % 5)
req_cnt++;
}
} else if (cmd->request_bufflen) { /* If data transfer. */
seg_cnt = 1;
} else {
seg_cnt = 0;
}
if ((req_cnt + 2) >= ha->req_q_cnt) {
/* Calculate number of free request entries. */
cnt = RD_REG_WORD(&reg->mailbox4);
if (ha->req_ring_index < cnt)
ha->req_q_cnt = cnt - ha->req_ring_index;
else
ha->req_q_cnt =
REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
}
/* If room for request in request ring. */
if ((req_cnt + 2) < ha->req_q_cnt) {
/* Check for room in outstanding command list. */
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS &&
ha->outstanding_cmds[cnt] != 0; cnt++) ;
if (cnt < MAX_OUTSTANDING_COMMANDS) {
ha->outstanding_cmds[cnt] = sp;
ha->req_q_cnt -= req_cnt;
CMD_HANDLE(sp->cmd) =
(unsigned char *)(unsigned long)cnt;
/*
* Build command packet.
*/
pkt = (cmd_a64_entry_t *) ha->request_ring_ptr;
pkt->entry_type = COMMAND_A64_TYPE;
pkt->entry_count = (uint8_t) req_cnt;
pkt->sys_define = (uint8_t) ha->req_ring_index;
pkt->handle = (uint32_t) cnt;
/* Zero out remaining portion of packet. */
memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8));
/* Set ISP command timeout. */
pkt->timeout = 30;
/* Set device target ID and LUN */
pkt->lun = SCSI_LUN_32(cmd);
pkt->target = SCSI_BUS_32(cmd) ?
(SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
/* Enable simple tag queuing if device supports it. */
if (cmd->device->tagged_queue)
pkt->control_flags |= BIT_3;
/* Load SCSI command packet. */
pkt->cdb_len = (uint16_t)CMD_CDBLEN(cmd);
memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), pkt->cdb_len);
/* dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */
/*
* Load data segments.
*/
if (seg_cnt) { /* If data transfer. */
/* Set transfer direction. */
if ((cmd->data_cmnd[0] == WRITE_6))
pkt->control_flags |= BIT_6;
else
pkt->control_flags |= (BIT_5 | BIT_6);
sp->dir = pkt->control_flags & (BIT_5 | BIT_6);
/* Set total data segment count. */
pkt->dseg_count = seg_cnt;
/* Setup packet address segment pointer. */
dword_ptr = (u32 *)&pkt->dseg_0_address;
if (cmd->use_sg) { /* If scatter gather */
/* Load command entry data segments. */
for (cnt = 0; cnt < 2 && seg_cnt;
cnt++, seg_cnt--) {
/* 3.13 64 bit */
*dword_ptr++ =
cpu_to_le32(pci_dma_lo32(sg_dma_address(sg)));
*dword_ptr++ =
cpu_to_le32(pci_dma_hi32(sg_dma_address(sg)));
*dword_ptr++ =
cpu_to_le32(sg_dma_len(sg));
sg++;
dprintk(1,
"S/G Segment phys_addr=%x %x, len=0x%x\n",
cpu_to_le32(pci_dma_hi32(sg_dma_address(sg))),
cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))),
cpu_to_le32(sg_dma_len(sg)));
}
dprintk(5,
"qla1280_64bit_start_scsi: Scatter/gather "
"command packet data - b %i, t %i, l %i \n",
SCSI_BUS_32(cmd),
SCSI_TCN_32(cmd),
SCSI_LUN_32(cmd));
qla1280_dump_buffer(5, (char *)pkt,
REQUEST_ENTRY_SIZE);
/*
* Build continuation packets.
*/
dprintk(1,
"S/G Building Continuation...seg_cnt=0x%x "
"remains\n", seg_cnt);
while (seg_cnt > 0) {
/* Adjust ring index. */
ha->req_ring_index++;
if (ha->req_ring_index ==
REQUEST_ENTRY_CNT) {
ha->req_ring_index = 0;
ha->request_ring_ptr =
ha->request_ring;
} else
ha->request_ring_ptr++;
pkt = (cmd_a64_entry_t *)ha->request_ring_ptr;
/* Zero out packet. */
memset(pkt, 0,
REQUEST_ENTRY_SIZE);
/* Load packet defaults. */
((cont_a64_entry_t *) pkt)->entry_type =
CONTINUE_A64_TYPE;
((cont_a64_entry_t *) pkt)->entry_count = 1;
((cont_a64_entry_t *) pkt)->sys_define =
(uint8_t)ha->req_ring_index;
/* Setup packet address segment pointer. */
dword_ptr =
(u32 *)&((cont_a64_entry_t *) pkt)->dseg_0_address;
/* Load continuation entry data segments. */
for (cnt = 0;
cnt < 5 && seg_cnt;
cnt++, seg_cnt--) {
/* 3.13 64 bit */
*dword_ptr++ =
cpu_to_le32(pci_dma_lo32(sg_dma_address(sg)));
*dword_ptr++ =
cpu_to_le32(pci_dma_hi32(sg_dma_address(sg)));
*dword_ptr++ =
cpu_to_le32(sg_dma_len(sg));
dprintk(1,
"S/G Segment Cont. phys_addr=%x %x, len=0x%x\n",
cpu_to_le32(pci_dma_hi32(sg_dma_address(sg))),
cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))),
cpu_to_le32(sg_dma_len(sg)));
sg++;
}
dprintk(5,
"qla1280_64bit_start_scsi: continuation "
"packet data - b %i, t %i, l %i \n",
SCSI_BUS_32(cmd),
SCSI_TCN_32(cmd),
SCSI_LUN_32(cmd));
qla1280_dump_buffer(5,
(char *)pkt,
REQUEST_ENTRY_SIZE);
}
} else { /* No scatter gather data transfer */
/* 3.13 64 bit */
dma_handle = pci_map_single(ha->pdev,
cmd->request_buffer,
cmd->request_bufflen,
scsi_to_pci_dma_dir(cmd->sc_data_direction));
/* save dma_handle for pci_unmap_single */
sp->saved_dma_handle = dma_handle;
*dword_ptr++ =
cpu_to_le32(pci_dma_lo32(dma_handle));
*dword_ptr++ =
cpu_to_le32(pci_dma_hi32(dma_handle));
*dword_ptr =
(uint32_t)cmd->request_bufflen;
/* dprintk(1,
"No S/G map_single saved_dma_handle=%lx\n",dma_handle);
*/
dprintk(5,
"qla1280_64bit_start_scsi: No scatter/gather "
"command packet data - b %i, t %i, l %i \n",
SCSI_BUS_32(cmd),
SCSI_TCN_32(cmd),
SCSI_LUN_32(cmd));
qla1280_dump_buffer(5, (char *)pkt,
REQUEST_ENTRY_SIZE);
}
} else { /* No data transfer */
dword_ptr = (uint32_t *)(pkt + 1);
*dword_ptr++ = 0;
*dword_ptr++ = 0;
*dword_ptr = 0;
dprintk(5,
"qla1280_64bit_start_scsi: No data, command "
"packet data - b %i, t %i, l %i \n",
SCSI_BUS_32(cmd), SCSI_TCN_32(cmd),
SCSI_LUN_32(cmd));
qla1280_dump_buffer(5, (char *)pkt,
REQUEST_ENTRY_SIZE);
}
/* Adjust ring index. */
ha->req_ring_index++;
if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
ha->req_ring_index = 0;
ha->request_ring_ptr = ha->request_ring;
} else
ha->request_ring_ptr++;
/* Set chip new ring index. */
dprintk(1,
"qla1280_64bit_start_scsi: Wakeup RISC for pending command\n");
ha->qthreads--;
sp->flags |= SRB_SENT;
ha->actthreads++;
WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
} else {
status = 1;
dprintk(2, "qla1280_64bit_start_scsi: NO ROOM IN "
"OUTSTANDING ARRAY, req_q_cnt=0x%x",
ha->req_q_cnt);
}
} else {
status = 1;
dprintk(2,
"qla1280_64bit_start_scsi: in-ptr=0x%x req_q_cnt=0x%x"
"req_cnt=0x%x", ha->req_ring_index, ha->req_q_cnt,
req_cnt);
}
if (status)
dprintk(2, "qla1280_64bit_start_scsi: **** FAILED ****\n");
else
dprintk(3, "qla1280_64bit_start_scsi: exiting normally\n");
return status;
}
#endif
/*
* qla1280_32bit_start_scsi
* The start SCSI is responsible for building request packets on
* request ring and modifying ISP input pointer.
*
* The Qlogic firmware interface allows every queue slot to have a SCSI
* command and up to 4 scatter/gather (SG) entries. If we need more
* than 4 SG entries, then continuation entries are used that can
* hold another 7 entries each. The start routine determines if there
* is eought empty slots then build the combination of requests to
* fulfill the OS request.
*
* Input:
* ha = adapter block pointer.
* sp = SCSI Request Block structure pointer.
*
* Returns:
* 0 = success, was able to issue command.
*/
static int
qla1280_32bit_start_scsi(struct scsi_qla_host *ha, srb_t * sp)
{
struct device_reg *reg = ha->iobase;
Scsi_Cmnd *cmd = sp->cmd;
cmd_entry_t *pkt;
struct scatterlist *sg = NULL;
uint32_t *dword_ptr;
int status = 0;
int cnt;
int req_cnt;
uint16_t seg_cnt;
dma_addr_t dma_handle;
ENTER("qla1280_32bit_start_scsi");
dprintk(1, "32bit_start: cmd=%p sp=%p CDB=%x\n", cmd, sp,
cmd->cmnd[0]);
/* Calculate number of entries and segments required. */
req_cnt = 1;
if (cmd->use_sg) {
/*
* We must build an SG list in adapter format, as the kernel's SG list
* cannot be used directly because of data field size (__alpha__)
* differences and the kernel SG list uses virtual addresses where
* we need physical addresses.
*/
sg = (struct scatterlist *) cmd->request_buffer;
/* 3.13 32 bit */
seg_cnt = pci_map_sg (ha->pdev, sg, cmd->use_sg,
scsi_to_pci_dma_dir(cmd->sc_data_direction));
/*
* if greater than four sg entries then we need to allocate
* continuation entries
*/
if (seg_cnt > 4) {
req_cnt += (seg_cnt - 4) / 7;
if ((seg_cnt - 4) % 7)
req_cnt++;
}
dprintk(1, "S/G Transfer cmd=%p seg_cnt=0x%x, req_cnt=%x\n",
cmd, seg_cnt, req_cnt);
} else if (cmd->request_bufflen) { /* If data transfer. */
dprintk(1, "No S/G transfer t=%x cmd=%p len=%x CDB=%x\n",
SCSI_TCN_32(cmd), cmd, cmd->request_bufflen,
cmd->cmnd[0]);
seg_cnt = 1;
} else {
/* dprintk(1, "No data transfer \n"); */
seg_cnt = 0;
}
if ((req_cnt + 2) >= ha->req_q_cnt) {
/* Calculate number of free request entries. */
cnt = RD_REG_WORD(&reg->mailbox4);
if (ha->req_ring_index < cnt)
ha->req_q_cnt = cnt - ha->req_ring_index;
else
ha->req_q_cnt =
REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
}
dprintk(1, "Number of free entries=(%d) seg_cnt=0x%x\n",
ha->req_q_cnt, seg_cnt);
/* If room for request in request ring. */
if ((req_cnt + 2) < ha->req_q_cnt) {
/* Check for empty slot in outstanding command list. */
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS &&
(ha->outstanding_cmds[cnt] != 0); cnt++) ;
if (cnt < MAX_OUTSTANDING_COMMANDS) {
CMD_HANDLE(sp->cmd) =
(unsigned char *) (unsigned long) cnt;
ha->outstanding_cmds[cnt] = sp;
ha->req_q_cnt -= req_cnt;
/*
* Build command packet.
*/
pkt = (cmd_entry_t *) ha->request_ring_ptr;
pkt->entry_type = COMMAND_TYPE;
pkt->entry_count = (uint8_t) req_cnt;
pkt->sys_define = (uint8_t) ha->req_ring_index;
pkt->handle = (uint32_t) cnt;
/* Zero out remaining portion of packet. */
memset(((char *)pkt + 8), 0, (REQUEST_ENTRY_SIZE - 8));
/* Set ISP command timeout. */
pkt->timeout = 30;
/* Set device target ID and LUN */
pkt->lun = SCSI_LUN_32(cmd);
pkt->target = SCSI_BUS_32(cmd) ?
(SCSI_TCN_32(cmd) | BIT_7) : SCSI_TCN_32(cmd);
/* Enable simple tag queuing if device supports it. */
if (cmd->device->tagged_queue)
pkt->control_flags |= BIT_3;
/* Load SCSI command packet. */
pkt->cdb_len = (uint16_t) CMD_CDBLEN(cmd);
memcpy(pkt->scsi_cdb, &(CMD_CDBP(cmd)), pkt->cdb_len);
/*dprintk(1, "Build packet for command[0]=0x%x\n",pkt->scsi_cdb[0]); */
/*
* Load data segments.
*/
if (seg_cnt) {
/* Set transfer direction (READ and WRITE) */
/* Linux doesn't tell us */
/*
* For block devices, cmd->request->cmd has the operation
* For character devices, this isn't always set properly, so
* we need to check data_cmnd[0]. This catches the conditions
* for st.c, but not sg. Generic commands are pass down to us.
*/
if ((cmd->data_cmnd[0] == WRITE_6))
pkt->control_flags |= BIT_6;
else
pkt->control_flags |= (BIT_5 | BIT_6);
sp->dir = pkt->control_flags & (BIT_5 | BIT_6);
/* Set total data segment count. */
pkt->dseg_count = seg_cnt;
/* Setup packet address segment pointer. */
dword_ptr = &pkt->dseg_0_address;
if (cmd->use_sg) { /* If scatter gather */
dprintk(1, "Building S/G data "
"segments..\n");
qla1280_dump_buffer(1, (char *)sg,
4 * 16);
/* Load command entry data segments. */
for (cnt = 0; cnt < 4 && seg_cnt;
cnt++, seg_cnt--) {
/* 3.13 32 bit */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
*dword_ptr++ =
cpu_to_le32(virt_to_bus(sg->address));
*dword_ptr++ = sg->length;
dprintk(1,
"S/G Segment phys_addr=0x%x, len=0x%x\n",
cpu_to_le32(virt_to_bus(sg->address)),
sg->length);
#else
*dword_ptr++ =
cpu_to_le32(pci_dma_lo32(sg_dma_address(sg)));
*dword_ptr++ =
cpu_to_le32(sg_dma_len(sg));
dprintk(1, "S/G Segment phys_addr=0x%x, len=0x%x\n",
cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))),
cpu_to_le32(sg_dma_len(sg)));
#endif
sg++;
}
/*
* Build continuation packets.
*/
dprintk(1, "S/G Building Continuation"
"...seg_cnt=0x%x remains\n",
seg_cnt);
while (seg_cnt > 0) {
/* Adjust ring index. */
ha->req_ring_index++;
if (ha->req_ring_index ==
REQUEST_ENTRY_CNT) {
ha->req_ring_index = 0;
ha->request_ring_ptr =
ha->request_ring;
} else
ha->request_ring_ptr++;
pkt = (cmd_entry_t *)
ha->request_ring_ptr;
/* Zero out packet. */
memset(pkt, 0,
REQUEST_ENTRY_SIZE);
/* Load packet defaults. */
((cont_entry_t *) pkt)->
entry_type = CONTINUE_TYPE;
((cont_entry_t *) pkt)->
entry_count = 1;
((cont_entry_t *) pkt)->
sys_define =
(uint8_t) ha->
req_ring_index;
/* Setup packet address segment pointer. */
dword_ptr =
&((cont_entry_t *) pkt)->dseg_0_address;
/* Load continuation entry data segments. */
for (cnt = 0;
cnt < 7 && seg_cnt;
cnt++, seg_cnt--) {
/* 3.13 32 bit */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
*dword_ptr++ =
cpu_to_le32(virt_to_bus(sg->address));
*dword_ptr++ = sg->length;
dprintk(1,
"S/G Segment Cont. phys_addr=0x%x, len=0x%x\n",
cpu_to_le32(pci_dma_lo32(virt_to_bus(sg->address))), sg->length);
#else
*dword_ptr++ =
cpu_to_le32(pci_dma_lo32(sg_dma_address(sg)));
*dword_ptr++ =
cpu_to_le32(sg_dma_len(sg));
dprintk(1,
"S/G Segment Cont. phys_addr=0x%x, "
"len=0x%x\n",
cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))),
cpu_to_le32(sg_dma_len(sg)));
#endif
sg++;
}
dprintk(5,
"qla1280_32bit_start_scsi: continuation "
"packet data - scsi(%i:%i:%i)\n",
SCSI_BUS_32(cmd),
SCSI_TCN_32(cmd),
SCSI_LUN_32(cmd));
qla1280_dump_buffer(5,
(char *)pkt,
REQUEST_ENTRY_SIZE);
}
} else { /* No S/G data transfer */
/* 3.13 32 bit */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
*dword_ptr++ =
cpu_to_le32 (virt_to_bus
(cmd->request_buffer));
#else
dma_handle = pci_map_single(ha->pdev,
cmd->request_buffer,
cmd->request_bufflen,
scsi_to_pci_dma_dir(cmd->sc_data_direction));
sp->saved_dma_handle = dma_handle;
*dword_ptr++ =
cpu_to_le32(pci_dma_lo32(dma_handle));
#endif
*dword_ptr =
(uint32_t)cmd->request_bufflen;
}
} else { /* No data transfer at all */
dword_ptr = (uint32_t *)(pkt + 1);
*dword_ptr++ = 0;
*dword_ptr = 0;
dprintk(5,
"qla1280_32bit_start_scsi: No data, command "
"packet data - \n");
qla1280_dump_buffer(5, (char *)pkt,
REQUEST_ENTRY_SIZE);
}
dprintk(5,
"qla1280_32bit_start_scsi: First IOCB block:\n");
qla1280_dump_buffer(5, (char *)ha->request_ring_ptr,
REQUEST_ENTRY_SIZE);
/* Adjust ring index. */
ha->req_ring_index++;
if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
ha->req_ring_index = 0;
ha->request_ring_ptr = ha->request_ring;
} else
ha->request_ring_ptr++;
/* Set chip new ring index. */
dprintk(1, "qla1280_32bit_start_scsi: Wakeup RISC "
"for pending command\n");
ha->qthreads--;
sp->flags |= SRB_SENT;
ha->actthreads++;
WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
} else {
status = 1;
dprintk(2,
"qla1280_32bit_start_scsi: NO ROOM IN OUTSTANDING "
"ARRAY, req_q_cnt=0x%x\n", ha->req_q_cnt);
}
} else {
status = 1;
dprintk(2,
"qla1280_32bit_start_scsi: in-ptr=0x%x, req_q_cnt=0x%x, "
"req_cnt=0x%x", ha->req_ring_index, ha->req_q_cnt,
req_cnt);
}
if (status)
dprintk(2, "qla1280_32bit_start_scsi: **** FAILED ****\n");
LEAVE("qla1280_32bit_start_scsi");
return status;
}
/*
* qla1280_req_pkt
* Function is responsible for locking ring and
* getting a zeroed out request packet.
*
* Input:
* ha = adapter block pointer.
*
* Returns:
* 0 = failed to get slot.
*/
static request_t *
qla1280_req_pkt(struct scsi_qla_host *ha)
{
struct device_reg *reg = ha->iobase;
request_t *pkt = 0;
int cnt;
uint32_t timer;
ENTER("qla1280_req_pkt");
/*
* This can be called from interrupt context, damn it!!!
*/
/* Wait for 30 seconds for slot. */
for (timer = 15000000; timer; timer--) {
if (ha->req_q_cnt > 0) {
/* Calculate number of free request entries. */
cnt = RD_REG_WORD(&reg->mailbox4);
if (ha->req_ring_index < cnt)
ha->req_q_cnt = cnt - ha->req_ring_index;
else
ha->req_q_cnt =
REQUEST_ENTRY_CNT - (ha->req_ring_index - cnt);
}
/* Found empty request ring slot? */
if (ha->req_q_cnt > 0) {
ha->req_q_cnt--;
pkt = ha->request_ring_ptr;
/* Zero out packet. */
memset(pkt, 0, REQUEST_ENTRY_SIZE);
/* Set system defined field. */
pkt->sys_define = (uint8_t) ha->req_ring_index;
/* Set entry count. */
pkt->entry_count = 1;
break;
}
udelay(2); /* 10 */
/* Check for pending interrupts. */
qla1280_poll(ha);
}
if (!pkt)
dprintk(2, "qla1280_req_pkt: **** FAILED ****\n");
else
dprintk(3, "qla1280_req_pkt: exiting normally\n");
return pkt;
}
/*
* qla1280_isp_cmd
* Function is responsible for modifying ISP input pointer.
* Releases ring lock.
*
* Input:
* ha = adapter block pointer.
*/
static void
qla1280_isp_cmd(struct scsi_qla_host *ha)
{
struct device_reg *reg = ha->iobase;
ENTER("qla1280_isp_cmd");
dprintk(5, "qla1280_isp_cmd: IOCB data:\n");
qla1280_dump_buffer(5, (char *)ha->request_ring_ptr,
REQUEST_ENTRY_SIZE);
/* Adjust ring index. */
ha->req_ring_index++;
if (ha->req_ring_index == REQUEST_ENTRY_CNT) {
ha->req_ring_index = 0;
ha->request_ring_ptr = ha->request_ring;
} else
ha->request_ring_ptr++;
/* Set chip new ring index. */
WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
LEAVE("qla1280_isp_cmd");
}
#if QL1280_LUN_SUPPORT
/*
* qla1280_enable_lun
* Issue enable LUN entry IOCB.
*
* Input:
* ha = adapter block pointer.
* bus = SCSI BUS number.
* lun = LUN number.
*/
static void
qla1280_enable_lun(struct scsi_qla_host *ha, int bus, int lun)
{
elun_entry_t *pkt;
ENTER("qla1280_enable_lun");
/* Get request packet. */
/*
if (pkt = (elun_entry_t *)qla1280_req_pkt(ha))
{
pkt->entry_type = ENABLE_LUN_TYPE;
pkt->lun = (uint16_t)(bus ? lun | BIT_15 : lun);
pkt->command_count = 32;
pkt->immed_notify_count = 1;
pkt->group_6_length = MAX_CMDSZ;
pkt->group_7_length = MAX_CMDSZ;
pkt->timeout = 0x30;
qla1280_isp_cmd(ha);
}
*/
pkt = (elun_entry_t *) 1;
if (!pkt)
dprintk(2, "qla1280_enable_lun: **** FAILED ****\n");
else
dprintk(3, "qla1280_enable_lun: exiting normally\n");
}
#endif
#if QL1280_TARGET_MODE_SUPPORT
/****************************************************************************/
/* Target Mode Support Functions. */
/****************************************************************************/
/*
* qla1280_notify_ack
* Issue notify acknowledge IOCB.
* If sequence ID is zero, acknowledgement of
* SCSI bus reset or bus device reset is assumed.
*
* Input:
* ha = adapter block pointer.
* inotify = immediate notify entry pointer.
*/
static void
qla1280_notify_ack(struct scsi_qla_host *ha, notify_entry_t * inotify)
{
nack_entry_t *pkt;
dprintk(3, "qla1280_notify_ack: entered\n");
/* Get request packet. */
if (pkt = (nack_entry_t *) qla1280_req_pkt(ha)) {
pkt->entry_type = NOTIFY_ACK_TYPE;
pkt->lun = inotify->lun;
pkt->initiator_id = inotify->initiator_id;
pkt->target_id = inotify->target_id;
if (inotify->seq_id == 0)
pkt->event = BIT_7;
else
pkt->seq_id = inotify->seq_id;
/* Issue command to ISP */
qla1280_isp_cmd(ha);
}
if (!pkt)
dprintk(2, "qla1280_notify_ack: **** FAILED ****\n");
else
dprintk(3, "qla1280_notify_ack: exiting normally\n");
}
/*
* qla1280_immed_notify
* Issue immediate notify IOCB for LUN 0.
*
* Input:
* ha = adapter block pointer.
* inotify = immediate notify entry pointer.
*/
static void
qla1280_immed_notify(struct scsi_qla_host *ha, notify_entry_t * inotify)
{
notify_entry_t *pkt;
dprintk(3, "qla1280_immed_notify: entered\n");
/* Get request packet. */
if (pkt = (notify_entry_t *) qla1280_req_pkt(ha)) {
pkt->entry_type = IMMED_NOTIFY_TYPE;
pkt->lun = inotify->lun;
pkt->initiator_id = inotify->initiator_id;
pkt->target_id = inotify->target_id;
pkt->status = 1;
/* Issue command to ISP */
qla1280_isp_cmd(ha);
}
if (!pkt)
dprintk(2, "qla1280_immed_notify: **** FAILED ****\n");
else
dprintk(3, "qla1280_immed_notify: exiting normally\n");
}
/*
* qla1280_accept_io
* Issue accept target I/O IOCB for LUN 0.
*
* Input:
* ha = adapter block pointer.
* ctio = ctio returned entry pointer.
*/
static void
qla1280_accept_io(struct scsi_qla_host *ha, ctio_ret_entry_t * ctio)
{
atio_entry_t *pkt;
dprintk(3, "qla1280_accept_io: entered\n");
/* Get request packet. */
if (pkt = (atio_entry_t *) qla1280_req_pkt(ha)) {
pkt->entry_type = ACCEPT_TGT_IO_TYPE;
pkt->lun = ctio->lun;
pkt->initiator_id = ctio->initiator_id;
pkt->target_id = ctio->target_id;
pkt->tag_value = ctio->tag_value;
pkt->status = 1;
/* Issue command to ISP */
qla1280_isp_cmd(ha);
}
if (!pkt)
dprintk(2, "qla1280_accept_io: **** FAILED ****\n");
else
dprintk(3, "qla1280_accept_io: exiting normally\n");
}
/*
* qla1280_64bit_continue_io
* Issue continue target I/O IOCB.
*
* Input:
* ha = adapter block pointer.
* atio = atio pointer.
* len = total bytecount.
* addr = physical address pointer.
*/
static void
qla1280_64bit_continue_io(struct scsi_qla_host *ha, atio_entry_t * atio,
uint32_t len, paddr32_t * addr)
{
ctio_a64_entry_t *pkt;
uint32_t *dword_ptr;
dprintk(3, "qla1280_64bit_continue_io: entered\n");
/* Get request packet. */
if (pkt = (ctio_a64_entry_t *) qla1280_req_pkt(ha)) {
pkt->entry_type = CTIO_A64_TYPE;
pkt->lun = atio->lun;
pkt->initiator_id = atio->initiator_id;
pkt->target_id = atio->target_id;
pkt->option_flags = atio->option_flags;
pkt->tag_value = atio->tag_value;
pkt->scsi_status = atio->scsi_status;
if (len) {
pkt->dseg_count = 1;
pkt->transfer_length = len;
pkt->dseg_0_length = len;
dword_ptr = (uint32_t *) addr;
pkt->dseg_0_address[0] = *dword_ptr++;
pkt->dseg_0_address[1] = *dword_ptr;
}
/* Issue command to ISP */
qla1280_isp_cmd(ha);
}
if (!pkt)
dprintk(2, "qla1280_64bit_continue_io: **** FAILED ****\n");
else
dprintk(3, "qla1280_64bit_continue_io: exiting normally\n");
}
/*
* qla1280_32bit_continue_io
* Issue continue target I/O IOCB.
*
* Input:
* ha = adapter block pointer.
* atio = atio pointer.
* len = total bytecount.
* addr = physical address pointer.
*/
static void
qla1280_32bit_continue_io(struct scsi_qla_host *ha, atio_entry_t * atio,
uint32_t len, paddr32_t * addr)
{
ctio_entry_t *pkt;
uint32_t *dword_ptr;
dprintk(3, "qla1280_32bit_continue_io: entered\n");
/* Get request packet. */
if (pkt = (ctio_entry_t *) qla1280_req_pkt(ha)) {
pkt->entry_type = CONTINUE_TGT_IO_TYPE;
pkt->lun = atio->lun;
pkt->initiator_id = atio->initiator_id;
pkt->target_id = atio->target_id;
pkt->option_flags = atio->option_flags;
pkt->tag_value = atio->tag_value;
pkt->scsi_status = atio->scsi_status;
if (len) {
pkt->dseg_count = 1;
pkt->transfer_length = len;
pkt->dseg_0_length = len;
dword_ptr = (uint32_t *) addr;
pkt->dseg_0_address = *dword_ptr;
}
/* Issue command to ISP */
qla1280_isp_cmd(ha);
}
if (!pkt)
dprintk(2, "qla1280_32bit_continue_io: **** FAILED ****\n");
else
dprintk(3, "qla1280_32bit_continue_io: exiting normally\n");
}
#endif /* QL1280_TARGET_MODE_SUPPORT */
/****************************************************************************/
/* Interrupt Service Routine. */
/****************************************************************************/
/****************************************************************************
* qla1280_isr
* Calls I/O done on command completion.
*
* Input:
* ha = adapter block pointer.
* done_q_first = done queue first pointer.
* done_q_last = done queue last pointer.
****************************************************************************/
static void
qla1280_isr(struct scsi_qla_host *ha, srb_t ** done_q_first,
srb_t ** done_q_last)
{
struct device_reg *reg = ha->iobase;
response_t *pkt;
srb_t *sp = 0;
uint16_t mailbox[MAILBOX_REGISTER_COUNT];
uint16_t *wptr;
uint32_t index;
u16 istatus;
ENTER("qla1280_isr");
istatus = RD_REG_WORD(&reg->istatus);
if (!(istatus & (RISC_INT | PCI_INT)))
return;
/* Save mailbox register 5 */
mailbox[5] = RD_REG_WORD(&reg->mailbox5);
/* Check for mailbox interrupt. */
mailbox[0] = RD_REG_WORD(&reg->semaphore);
if (mailbox[0] & BIT_0) {
/* Get mailbox data. */
/* dprintk(1, "qla1280_isr: In Get mailbox data \n"); */
wptr = &mailbox[0];
*wptr++ = RD_REG_WORD(&reg->mailbox0);
*wptr++ = RD_REG_WORD(&reg->mailbox1);
*wptr = RD_REG_WORD(&reg->mailbox2);
if (mailbox[0] != MBA_SCSI_COMPLETION) {
wptr++;
*wptr++ = RD_REG_WORD(&reg->mailbox3);
*wptr++ = RD_REG_WORD(&reg->mailbox4);
wptr++;
*wptr++ = RD_REG_WORD(&reg->mailbox6);
*wptr = RD_REG_WORD(&reg->mailbox7);
}
/* Release mailbox registers. */
WRT_REG_WORD(&reg->semaphore, 0);
WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
dprintk(5, "qla1280_isr: mailbox interrupt mailbox[0] = 0x%x",
mailbox[0]);
/* Handle asynchronous event */
switch (mailbox[0]) {
case MBA_SCSI_COMPLETION: /* Response completion */
dprintk(5,
"qla1280_isr: mailbox SCSI response completion\n");
if (ha->flags.online) {
/* Get outstanding command index. */
index = mailbox[2] << 16 | mailbox[1];
/* Validate handle. */
if (index < MAX_OUTSTANDING_COMMANDS)
sp = ha->outstanding_cmds[index];
else
sp = 0;
if (sp) {
/* Free outstanding command slot. */
ha->outstanding_cmds[index] = 0;
/* Save ISP completion status */
CMD_RESULT(sp->cmd) = 0;
/* Place block on done queue */
sp->s_next = NULL;
sp->s_prev = *done_q_last;
if (!*done_q_first)
*done_q_first = sp;
else
(*done_q_last)->s_next = sp;
*done_q_last = sp;
} else {
/*
* If we get here we have a real problem!
*/
printk(KERN_WARNING
"qla1280: ISP invalid handle");
ha->flags.isp_abort_needed = TRUE;
}
}
break;
case MBA_BUS_RESET: /* SCSI Bus Reset */
ha->flags.reset_marker = TRUE;
index = mailbox[6] & BIT_0;
ha->bus_settings[index].reset_marker = TRUE;
printk(KERN_DEBUG
"qla1280_isr(): index %i asynchronous "
"BUS_RESET\n", index);
break;
case MBA_SYSTEM_ERR: /* System Error */
printk(KERN_WARNING
"qla1280: ISP System Error - mbx1=%xh, mbx2=%xh, "
"mbx3=%xh\n", mailbox[1], mailbox[2],
mailbox[3]);
ha->flags.isp_abort_needed = TRUE;
break;
case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */
printk(KERN_WARNING
"qla1280: ISP Request Transfer Error\n");
ha->flags.isp_abort_needed = TRUE;
break;
case MBA_RSP_TRANSFER_ERR: /* Response Transfer Error */
printk(KERN_WARNING
"qla1280: ISP Response Transfer Error\n");
ha->flags.isp_abort_needed = TRUE;
break;
case MBA_WAKEUP_THRES: /* Request Queue Wake-up */
dprintk(2, "qla1280_isr: asynchronous WAKEUP_THRES\n");
break;
case MBA_TIMEOUT_RESET: /* Execution Timeout Reset */
dprintk(2,
"qla1280_isr: asynchronous TIMEOUT_RESET\n");
break;
case MBA_DEVICE_RESET: /* Bus Device Reset */
dprintk(2,
"qla1280_isr: asynchronous BUS_DEVICE_RESET\n");
printk(KERN_INFO "qla1280_isr(): asynchronous "
"BUS_DEVICE_RESET\n");
ha->flags.reset_marker = TRUE;
index = mailbox[6] & BIT_0;
ha->bus_settings[index].reset_marker = TRUE;
break;
case MBA_BUS_MODE_CHANGE:
dprintk(2,
"qla1280_isr: asynchronous BUS_MODE_CHANGE\n");
break;
default:
/* dprintk(1, "qla1280_isr: default case of switch MB \n"); */
if (mailbox[0] < MBA_ASYNC_EVENT) {
wptr = &mailbox[0];
memcpy((uint16_t *) ha->mailbox_out, wptr,
MAILBOX_REGISTER_COUNT *
sizeof(uint16_t));
ha->flags.mbox_int = TRUE;
}
break;
}
} else {
WRT_REG_WORD(&reg->host_cmd, HC_CLR_RISC_INT);
}
/*
* Response ring - waiting for the mbox_busy flag here seems
* unnecessary as the mailbox data has been copied to ha->mailbox_out
* by the time we actually get here!
*/
if (ha->flags.online
#if 0
&& !ha->flags.mbox_busy
#endif
) {
if (mailbox[5] < RESPONSE_ENTRY_CNT) {
while (ha->rsp_ring_index != mailbox[5]) {
pkt = ha->response_ring_ptr;
dprintk(5,
"qla1280_isr: ha->rsp_ring_index = 0x%x, "
"mailbox[5] = 0x%x\n",
ha->rsp_ring_index, mailbox[5]);
dprintk(5,
"qla1280_isr: response packet data\n");
qla1280_dump_buffer(5, (char *)pkt,
RESPONSE_ENTRY_SIZE);
if (pkt->entry_type == STATUS_TYPE) {
if ((pkt->scsi_status & 0xff)
|| pkt->comp_status
|| pkt->entry_status) {
dprintk(2,
"qla1280_isr: ha->rsp_ring_index = 0x%x"
"mailbox[5] = 0x%x, comp_status = 0x%x, "
"scsi_status = 0x%x\n",
ha->rsp_ring_index,
mailbox[5],
pkt->comp_status,
pkt->scsi_status);
}
} else {
dprintk(2,
"qla1280_isr: ha->rsp_ring_index = 0x%x, "
"mailbox[5] = 0x%x\n",
ha->rsp_ring_index,
mailbox[5]);
dprintk(2,
"qla1280_isr: response packet data\n");
qla1280_dump_buffer(2, (char *)pkt,
RESPONSE_ENTRY_SIZE);
}
if (pkt->entry_type == STATUS_TYPE
|| pkt->entry_status) {
if (pkt->entry_type == STATUS_TYPE)
qla1280_status_entry(ha,
(sts_entry_t *) pkt,
done_q_first,
done_q_last);
else
qla1280_error_entry(ha, pkt,
done_q_first,
done_q_last);
/* Adjust ring index. */
ha->rsp_ring_index++;
if (ha->rsp_ring_index ==
RESPONSE_ENTRY_CNT) {
ha->rsp_ring_index = 0;
ha->response_ring_ptr =
ha->response_ring;
} else
ha->response_ring_ptr++;
WRT_REG_WORD(&reg->mailbox5,
ha->rsp_ring_index);
}
#if QLA1280_TARGET_MODE_SUPPORT
else {
pkt = &response_entry;
/* Copy packet. */
dptr1 =
(uint32_t *)ha->response_ring_ptr;
dptr2 = (uint32_t *) pkt;
for (index = 0;
index < RESPONSE_ENTRY_SIZE / 4;
index++)
*dptr2++ = *dptr1++;
/* Adjust ring index. */
ha->rsp_ring_index++;
if (ha->rsp_ring_index ==
RESPONSE_ENTRY_CNT) {
ha->rsp_ring_index = 0;
ha->response_ring_ptr =
ha->response_ring;
} else
ha->response_ring_ptr++;
WRT_REG_WORD(&reg->mailbox5,
ha->rsp_ring_index);
switch (pkt->entry_type) {
case ACCEPT_TGT_IO_TYPE:
qla1280_atio_entry(ha,
(atio_entry_t *) pkt);
break;
case IMMED_NOTIFY_TYPE:
qla1280_notify_entry(ha,
(notify_entry_t *) pkt);
break;
case CTIO_RET_TYPE:
qla1280_accept_io(ha,
(ctio_ret_entry_t *) pkt);
break;
default:
break;
}
}
#endif
}
} else {
ha->flags.isp_abort_needed = TRUE;
dprintk(2, "qla1280_isr: Response pointer Error\n");
}
}
LEAVE("qla1280_isr");
}
/*
* qla1280_rst_aen
* Processes asynchronous reset.
*
* Input:
* ha = adapter block pointer.
*/
static void
qla1280_rst_aen(struct scsi_qla_host *ha)
{
#if QL1280_TARGET_MODE_SUPPORT
notify_entry_t nentry;
#endif
uint8_t bus;
ENTER("qla1280_rst_aen");
if (ha->flags.online && !ha->flags.reset_active &&
!ha->flags.abort_isp_active) {
ha->flags.reset_active = TRUE;
while (ha->flags.reset_marker) {
/* Issue marker command. */
ha->flags.reset_marker = FALSE;
for (bus = 0; bus < ha->ports &&
!ha->flags.reset_marker; bus++) {
if (ha->bus_settings[bus].reset_marker) {
ha->bus_settings[bus].reset_marker =
FALSE;
qla1280_marker(ha, bus, 0, 0,
MK_SYNC_ALL);
if (!ha->flags.reset_marker) {
#if QL1280_TARGET_MODE_SUPPORT
/* Issue notify acknowledgement command. */
memset(&nentry, 0,
sizeof(notify_entry_t));
nentry.initiator_id =
nentry.target_id =
bus ? ha->bus_settings[bus].id | BIT_7 :
ha->bus_settings[bus].id;
qla1280_notify_entry(ha,
&nentry);
#endif
/* Asynchronous event notification */
}
}
}
}
}
LEAVE("qla1280_rst_aen");
}
#if QL1280_TARGET_MODE_SUPPORT
/*
* qla1280_atio_entry
* Processes received ISP accept target I/O entry.
*
* Input:
* ha = adapter block pointer.
* pkt = entry pointer.
*/
static void
qla1280_atio_entry(struct scsi_qla_host *ha, atio_entry_t * pkt)
{
uint64_t *a64;
uint64_t *end_a64;
paddr32_t phy_addr[2];
paddr32_t end_addr[2];
uint32_t len;
uint32_t offset;
uint8_t t;
uint8_t *sense_ptr;
dprintk(3, "qla1280_atio_entry: entered\n");
t = pkt->initiator_id;
sense_ptr = ha->tsense + t * TARGET_SENSE_SIZE;
a64 = (uint64_t *)&phy_addr[0];
end_a64 = (uint64_t *)&end_addr[0];
switch (pkt->status & ~BIT_7) {
case 7: /* Path invalid */
dprintk(2, "qla1280_atio_entry: Path invalid\n");
break;
case 0x14: /* Target Bus Phase Sequence Failure */
dprintk(2, "qla1280_atio_entry: Target Bus Phase "
"Sequence Failure\n");
if (pkt->status & BIT_7) {
memcpy(sense_ptr, &pkt->sense_data, TARGET_SENSE_SIZE);
} else {
memset(sense_ptr, 0, TARGET_SENSE_SIZE);
*sense_ptr = 0x70;
*(sense_ptr + 2) = SD_HARDERR;
*(sense_ptr + 7) = TARGET_SENSE_SIZE - 8;
*(sense_ptr + 12) = SC_SELFAIL;
}
pkt->scsi_status = S_CKCON;
pkt->option_flags |= OF_SSTS | OF_NO_DATA;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18)
if (ha->flags.enable_64bit_addressing)
qla1280_64bit_continue_io(ha, pkt, 0, 0);
else
#endif
qla1280_32bit_continue_io(ha, pkt, 0, 0);
break;
case 0x16: /* Requested Capability Not Available */
dprintk(2, "qla1280_atio_entry: Target Bus Phase "
"Sequence Failure\n");
break;
case 0x17: /* Bus Device Reset Message Received */
dprintk(2, "qla1280_atio_entry: Target Bus Phase "
"Sequence Failure\n");
break;
case 0x3D: /* CDB Received */
/* Check for invalid LUN */
if (pkt->lun && pkt->cdb[0] != SS_INQUIR &&
pkt->cdb[0] != SS_REQSEN)
pkt->cdb[0] = SS_TEST;
switch (pkt->cdb[0]) {
case SS_TEST:
dprintk(3, "qla1280_atio_entry: SS_TEST\n");
memset(sense_ptr, 0, TARGET_SENSE_SIZE);
len = 0;
if (pkt->lun == 0)
pkt->scsi_status = S_GOOD;
else {
*sense_ptr = 0x70;
*(sense_ptr + 2) = SD_ILLREQ;
*(sense_ptr + 7) = TARGET_SENSE_SIZE - 8;
*(sense_ptr + 12) = SC_INVLUN;
pkt->scsi_status = S_CKCON;
}
pkt->option_flags |= (OF_SSTS | OF_NO_DATA);
break;
case SS_REQSEN:
dprintk(3, "qla1280_atio_entry: SS_REQSEN\n");
phy_addr[0] = ha->tsense_dma;
phy_addr[1] = 0;
*a64 += t * TARGET_SENSE_SIZE;
if (pkt->cdb[4] > TARGET_SENSE_SIZE)
len = TARGET_SENSE_SIZE;
else
len = pkt->cdb[4];
pkt->scsi_status = S_GOOD;
pkt->option_flags |= (OF_SSTS | OF_DATA_IN);
break;
case SS_INQUIR:
dprintk(3, "qla1280_atio_entry: SS_INQUIR\n");
memset(sense_ptr, 0, TARGET_SENSE_SIZE);
phy_addr[0] = ha->tbuf_dma;
phy_addr[1] = 0;
*a64 += TARGET_INQ_OFFSET;
if (pkt->lun == 0) {
ha->tbuf->inq.id_type = ID_PROCESOR;
ha->tbuf->inq.id_pqual = ID_QOK;
} else {
ha->tbuf->inq.id_type = ID_NODEV;
ha->tbuf->inq.id_pqual = ID_QNOLU;
}
if (pkt->cdb[4] > sizeof(struct ident))
len = sizeof(struct ident);
else
len = pkt->cdb[4];
pkt->scsi_status = S_GOOD;
pkt->option_flags |= (OF_SSTS | OF_DATA_IN);
break;
case SM_WRDB:
memset(sense_ptr, 0, TARGET_SENSE_SIZE);
offset = pkt->cdb[5];
offset |= pkt->cdb[4] << 8;
offset |= pkt->cdb[3] << 16;
len = pkt->cdb[8];
len |= pkt->cdb[7] << 8;
len |= pkt->cdb[6] << 16;
end_addr[0] = phy_addr[0] = ha->tbuf_dma;
end_addr[1] = phy_addr[1] = 0;
*end_a64 += TARGET_DATA_OFFSET + TARGET_DATA_SIZE;
switch (pkt->cdb[1] & 7) {
case RW_BUF_HDATA:
dprintk(3, "qla1280_atio_entry: SM_WRDB, "
"RW_BUF_HDATA\n");
if (len > TARGET_DATA_SIZE + 4) {
dprintk(2,
"qla1280_atio_entry: SM_WRDB, "
"length > buffer size\n");
*sense_ptr = 0x70;
*(sense_ptr + 2) = SD_ILLREQ;
*(sense_ptr + 7) =
TARGET_SENSE_SIZE - 8;
*(sense_ptr + 12) = SC_ILLCDB;
pkt->scsi_status = S_CKCON;
pkt->option_flags |=
(OF_SSTS | OF_NO_DATA);
len = 0;
} else if (len) {
pkt->scsi_status = S_GOOD;
pkt->option_flags |=
(OF_SSTS | OF_DATA_OUT);
dprintk(3,
"qla1280_atio_entry: Issuing "
"SDI_TARMOD_WRCOMP\n");
sdi_xaen(SDI_TARMOD_WRCOMP, ha->cntlr,
pkt->target_id, pkt->lun, 0,
offset);
} else {
dprintk(2,
"qla1280_atio_entry: SM_WRDB, "
"zero length\n");
pkt->scsi_status = S_GOOD;
pkt->option_flags |=
(OF_SSTS | OF_NO_DATA);
}
break;
case RW_BUF_DATA:
dprintk(3, "qla1280_atio_entry: SM_WRDB, "
"RW_BUF_DATA\n");
*a64 += offset + TARGET_DATA_OFFSET;
if (pkt->cdb[2] != 0 || *a64 >= *end_a64 ||
*a64 + len > *end_a64) {
dprintk(2,
"qla1280_atio_entry: SM_WRDB, "
"RW_BUF_DATA BAD\n");
dprintk(2, "buf_id=0x%x, offset=0x%x, "
"length=0x%x\n", pkt->cdb[2],
offset, len);
*sense_ptr = 0x70;
*(sense_ptr + 2) = SD_ILLREQ;
*(sense_ptr + 7) =
TARGET_SENSE_SIZE - 8;
*(sense_ptr + 12) = SC_ILLCDB;
len = 0;
pkt->scsi_status = S_CKCON;
pkt->option_flags |=
(OF_SSTS | OF_NO_DATA);
} else if (len) {
pkt->scsi_status = S_GOOD;
pkt->option_flags |=
(OF_SSTS | OF_DATA_OUT);
dprintk(3,
"qla1280_atio_entry: Issuing "
"SDI_TARMOD_WRCOMP\n");
sdi_xaen(SDI_TARMOD_WRCOMP, ha->cntlr,
pkt->target_id, pkt->lun, 0,
offset);
} else {
dprintk(2,
"qla1280_atio_entry: SM_WRDB, "
"zero length\n");
pkt->scsi_status = S_GOOD;
pkt->option_flags |=
(OF_SSTS | OF_NO_DATA);
}
break;
default:
dprintk(2, "qla1280_atio_entry: SM_WRDB "
"unknown mode\n");
*sense_ptr = 0x70;
*(sense_ptr + 2) = SD_ILLREQ;
*(sense_ptr + 7) = TARGET_SENSE_SIZE - 8;
*(sense_ptr + 12) = SC_ILLCDB;
len = 0;
pkt->scsi_status = S_CKCON;
pkt->option_flags |= (OF_SSTS | OF_NO_DATA);
break;
}
break;
case SM_RDDB:
memset(sense_ptr, 0, TARGET_SENSE_SIZE);
offset = pkt->cdb[5];
offset |= pkt->cdb[4] << 8;
offset |= pkt->cdb[3] << 16;
len = pkt->cdb[8];
len |= pkt->cdb[7] << 8;
len |= pkt->cdb[6] << 16;
end_addr[0] = phy_addr[0] = ha->tbuf_dma;
end_addr[1] = phy_addr[1] = 0;
*end_a64 += TARGET_DATA_OFFSET + TARGET_DATA_SIZE;
switch (pkt->cdb[1] & 7) {
case RW_BUF_HDATA:
dprintk(3, "qla1280_atio_entry: SM_RDDB, "
"RW_BUF_HDATA\n");
if (len) {
ha->tbuf->hdr[0] = 0;
ha->tbuf->hdr[1] =
(TARGET_DATA_SIZE >> 16) & 0xff;
ha->tbuf->hdr[2] =
(TARGET_DATA_SIZE >> 8) & 0xff;
ha->tbuf->hdr[3] =
TARGET_DATA_SIZE & 0xff;
if (len > TARGET_DATA_SIZE + 4)
len = TARGET_DATA_SIZE + 4;
pkt->scsi_status = S_GOOD;
pkt->option_flags |=
(OF_SSTS | OF_DATA_IN);
} else {
dprintk(2,
"qla1280_atio_entry: SM_RDDB, "
"zero length\n");
pkt->scsi_status = S_GOOD;
pkt->option_flags |=
(OF_SSTS | OF_NO_DATA);
}
break;
case RW_BUF_DATA:
dprintk(3, "qla1280_atio_entry: SM_RDDB, "
"RW_BUF_DATA\n");
*a64 += offset + TARGET_DATA_OFFSET;
if (pkt->cdb[2] != 0 || *a64 >= *end_a64) {
dprintk(2,
"qla1280_atio_entry: SM_RDDB, "
"RW_BUF_DATA BAD\n");
dprintk(2, "buf_id=0x%x, offset=0x%x\n"
pkt->cdb[2], offset);
*sense_ptr = 0x70;
*(sense_ptr + 2) = SD_ILLREQ;
*(sense_ptr + 7) =
TARGET_SENSE_SIZE - 8;
*(sense_ptr + 12) = SC_ILLCDB;
len = 0;
pkt->scsi_status = S_CKCON;
pkt->option_flags |=
(OF_SSTS | OF_NO_DATA);
} else {
if (*a64 + len > *end_a64)
len = *end_a64 - *a64;
if (len) {
pkt->scsi_status = S_GOOD;
pkt->option_flags |=
(OF_SSTS | OF_DATA_IN);
} else {
dprintk(2,
"qla1280_atio_entry: SM_RDDB, "
"zero length\n");
pkt->scsi_status = S_GOOD;
pkt->option_flags |=
(OF_SSTS | OF_NO_DATA);
}
}
break;
case RW_BUF_DESC:
dprintk(3, "qla1280_atio_entry: SM_RDDB, "
"RW_BUF_DESC\n");
if (len) {
if (len > 4)
len = 4;
ha->tbuf->hdr[0] = 0;
if (pkt->cdb[2] != 0) {
ha->tbuf->hdr[1] = 0;
ha->tbuf->hdr[2] = 0;
ha->tbuf->hdr[3] = 0;
} else {
ha->tbuf->hdr[1] =
(TARGET_DATA_SIZE >> 16) &
0xff;
ha->tbuf->hdr[2] =
(TARGET_DATA_SIZE >> 8) &
0xff;
ha->tbuf->hdr[3] =
TARGET_DATA_SIZE & 0xff;
}
pkt->scsi_status = S_GOOD;
pkt->option_flags |=
(OF_SSTS | OF_DATA_IN);
} else {
dprintk(2,
"qla1280_atio_entry: SM_RDDB,"
" zero length\n");
pkt->scsi_status = S_GOOD;
pkt->option_flags |=
(OF_SSTS | OF_NO_DATA);
}
break;
default:
dprintk(2, "qla1280_atio_entry: SM_RDDB "
"unknown mode\n");
*sense_ptr = 0x70;
*(sense_ptr + 2) = SD_ILLREQ;
*(sense_ptr + 7) = TARGET_SENSE_SIZE - 8;
*(sense_ptr + 12) = SC_ILLCDB;
len = 0;
pkt->scsi_status = S_CKCON;
pkt->option_flags |= (OF_SSTS | OF_NO_DATA);
break;
}
break;
default:
dprintk(2,
"qla1280_atio_entry: Unknown SCSI command\n");
qla1280_dump_buffer(2, &pkt->cdb[0], pkt->cdb_len);
memset(sense_ptr, 0, TARGET_SENSE_SIZE);
*sense_ptr = 0x70;
*(sense_ptr + 2) = SD_ILLREQ;
*(sense_ptr + 7) = TARGET_SENSE_SIZE - 8;
*(sense_ptr + 12) = SC_INVOPCODE;
len = 0;
pkt->scsi_status = S_CKCON;
pkt->option_flags |= (OF_SSTS | OF_NO_DATA);
break;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,18)
if (ha->flags.enable_64bit_addressing)
qla1280_64bit_continue_io(ha, pkt, len,
(paddr32_t *)&phy_addr);
else
#endif
qla1280_32bit_continue_io(ha, pkt, len,
(paddr32_t *)&phy_addr);
break;
default:
break;
}
dprintk(3, "qla1280_atio_entry: exiting normally\n");
}
/*
* qla1280_notify_entry
* Processes received ISP immediate notify entry.
*
* Input:
* ha = adapter block pointer.
* pkt = entry pointer.
*/
static void
qla1280_notify_entry(struct scsi_qla_host *ha, notify_entry_t * pkt)
{
dprintk(3, "qla1280_notify_entry: entered\n");
/* Acknowledge immediate notify */
qla1280_notify_ack(ha, pkt);
/* Issue notify entry to increment resource count */
qla1280_immed_notify(ha, pkt);
dprintk(3, "qla1280_notify_entry: exiting normally\n");
}
#endif /* QLA1280_TARGET_MODE_SUPPORT */
/*
* qla1280_status_entry
* Processes received ISP status entry.
*
* Input:
* ha = adapter block pointer.
* pkt = entry pointer.
* done_q_first = done queue first pointer.
* done_q_last = done queue last pointer.
*/
static void
qla1280_status_entry(struct scsi_qla_host *ha, sts_entry_t * pkt,
srb_t ** done_q_first, srb_t ** done_q_last)
{
unsigned int bus, target, lun;
int sense_sz;
srb_t *sp;
scsi_lu_t *q;
Scsi_Cmnd *cmd;
ENTER("qla1280_status_entry");
/* Validate handle. */
if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
sp = ha->outstanding_cmds[pkt->handle];
else
sp = 0;
if (sp) {
/* Free outstanding command slot. */
ha->outstanding_cmds[pkt->handle] = 0;
cmd = sp->cmd;
/* Generate LU queue on cntrl, target, LUN */
bus = SCSI_BUS_32(cmd);
target = SCSI_TCN_32(cmd);
lun = SCSI_LUN_32(cmd);
q = LU_Q(ha, bus, target, lun);
if (pkt->comp_status || pkt->scsi_status) {
dprintk(1, "scsi: comp_status = 0x%x, scsi_status = "
"0x%x, handle = 0x%x\n", pkt->comp_status,
pkt->scsi_status, pkt->handle);
}
/* Target busy */
if (pkt->scsi_status & SS_BUSY_CONDITION &&
pkt->scsi_status != SS_RESERVE_CONFLICT) {
CMD_RESULT(cmd) =
DID_BUS_BUSY << 16 | (pkt->scsi_status & 0xff);
} else {
/* Save ISP completion status */
CMD_RESULT(cmd) = qla1280_return_status(pkt, cmd);
if (pkt->scsi_status & SS_CHECK_CONDITION) {
if (pkt->comp_status != CS_ARS_FAILED) {
if (pkt->req_sense_length <
CMD_SNSLEN(cmd))
sense_sz = pkt->req_sense_length;
else
/*
* Scsi_Cmnd->sense_buffer is
* 64 bytes, why only copy 63?
* This looks wrong! /Jes
*/
sense_sz = CMD_SNSLEN(cmd) - 1;
memcpy(cmd->sense_buffer,
&pkt->req_sense_data, sense_sz);
} else
sense_sz = 0;
memset(cmd->sense_buffer + sense_sz, 0,
sizeof(cmd->sense_buffer) - sense_sz);
dprintk(2, "qla1280_status_entry: Check "
"condition Sense data, b %i, t %i, "
"l %i\n", bus, target, lun);
if (sense_sz)
qla1280_dump_buffer(2, (char *)cmd->sense_buffer,
sense_sz);
}
}
/* Place command on done queue. */
qla1280_done_q_put(sp, done_q_first, done_q_last);
} else {
printk(KERN_WARNING "qla1280: Status Entry invalid handle\n");
ha->flags.isp_abort_needed = TRUE;
}
LEAVE("qla1280_status_entry");
}
/*
* qla1280_error_entry
* Processes error entry.
*
* Input:
* ha = adapter block pointer.
* pkt = entry pointer.
* done_q_first = done queue first pointer.
* done_q_last = done queue last pointer.
*/
static void
qla1280_error_entry(struct scsi_qla_host *ha, response_t * pkt,
srb_t ** done_q_first, srb_t ** done_q_last)
{
srb_t *sp;
ENTER("qla1280_error_entry");
if (pkt->entry_status & BIT_3)
dprintk(2, "qla1280_error_entry: BAD PAYLOAD flag error\n");
else if (pkt->entry_status & BIT_2)
dprintk(2, "qla1280_error_entry: BAD HEADER flag error\n");
else if (pkt->entry_status & BIT_1)
dprintk(2, "qla1280_error_entry: FULL flag error\n");
else
dprintk(2, "qla1280_error_entry: UNKNOWN flag error\n");
/* Validate handle. */
if (pkt->handle < MAX_OUTSTANDING_COMMANDS)
sp = ha->outstanding_cmds[pkt->handle];
else
sp = 0;
if (sp) {
/* Free outstanding command slot. */
ha->outstanding_cmds[pkt->handle] = 0;
/* Bad payload or header */
if (pkt->entry_status & (BIT_3 + BIT_2)) {
/* Bad payload or header, set error status. */
/* CMD_RESULT(sp->cmd) = CS_BAD_PAYLOAD; */
CMD_RESULT(sp->cmd) = DID_ERROR << 16;
} else if (pkt->entry_status & BIT_1) { /* FULL flag */
CMD_RESULT(sp->cmd) = DID_BUS_BUSY << 16;
} else {
/* Set error status. */
CMD_RESULT(sp->cmd) = DID_ERROR << 16;
}
/* Place command on done queue. */
qla1280_done_q_put(sp, done_q_first, done_q_last);
}
#ifdef QLA_64BIT_PTR
else if (pkt->entry_type == COMMAND_A64_TYPE) {
printk(KERN_WARNING "!qla1280: Error Entry invalid handle");
ha->flags.isp_abort_needed = TRUE;
}
#endif
LEAVE("qla1280_error_entry");
}
/*
* qla1280_abort_isp
* Resets ISP and aborts all outstanding commands.
*
* Input:
* ha = adapter block pointer.
*
* Returns:
* 0 = success
*/
static int
qla1280_abort_isp(struct scsi_qla_host *ha)
{
#if 0
struct device_reg *reg = ha->iobase;
#endif
srb_t *sp;
scsi_lu_t *q;
int status = 0;
int cnt;
int bus, target, lun;
ENTER("qla1280_abort_isp");
ha->flags.isp_abort_needed = FALSE;
if (!ha->flags.abort_isp_active && ha->flags.online) {
ha->flags.abort_isp_active = TRUE;
/* Disable ISP interrupts. */
qla1280_disable_intrs(ha);
/* Dequeue all commands in outstanding command list. */
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
sp = ha->outstanding_cmds[cnt];
if (sp) {
ha->outstanding_cmds[cnt] = 0;
/* Generate LU queue on controller, target, LUN */
bus = SCSI_BUS_32(sp->cmd);
target = SCSI_TCN_32(sp->cmd);
lun = SCSI_LUN_32(sp->cmd);
q = LU_Q(ha, bus, target, lun);
/* Reset outstanding command count. */
q->q_outcnt = 0;
q->q_flag &= ~QLA1280_QBUSY;
q->q_flag = 0;
/* Adjust watchdog timer for command. */
/* if (sp->flags & SRB_WATCHDOG)
sp->timeout += 2; */
/* Place request back on top of device queue. */
sp->flags = 0;
qla1280_putq_t(q, sp);
}
}
/* If firmware needs to be loaded */
if (qla1280_isp_firmware (ha)) {
if (!(status = qla1280_chip_diag(ha)))
status = qla1280_setup_chip(ha);
}
if (!status) {
/* Setup adapter based on NVRAM parameters. */
qla1280_nvram_config (ha);
if (!(status = qla1280_init_rings(ha))) {
/* Issue SCSI reset. */
for (bus = 0; bus < ha->ports; bus++) {
qla1280_bus_reset(ha, bus);
}
do {
/* Issue marker command. */
ha->flags.reset_marker = FALSE;
for (bus = 0; bus < ha->ports; bus++) {
ha->bus_settings[bus].
reset_marker = FALSE;
qla1280_marker(ha, bus, 0, 0,
MK_SYNC_ALL);
}
} while (ha->flags.reset_marker);
/* Enable host adapter target mode. */
for (bus = 0; bus < ha->ports; bus++) {
if (!
(status =
qla1280_enable_tgt(ha, bus))) {
for (cnt = 0; cnt < MAX_LUNS;
cnt++) {
/* qla1280_enable_lun(ha, bus, cnt); */
qla1280_poll(ha);
}
} else
break;
}
if (!status) {
/* Enable ISP interrupts. */
qla1280_enable_intrs(ha);
ha->flags.abort_isp_active = FALSE;
/* Restart queues that may have been stopped. */
qla1280_restart_queues(ha);
}
}
}
}
if (status) {
printk(KERN_WARNING
"qla1280: ISP error recovery failed, board disabled");
qla1280_reset_adapter(ha);
qla1280_abort_queues(ha);
dprintk(2, "qla1280_abort_isp: **** FAILED ****\n");
}
LEAVE("qla1280_abort_isp");
return status;
}
/*
* qla1280_restart_queues
* Restart all device queues.
*
* Input:
* ha = adapter block pointer.
*/
static void
qla1280_restart_queues(struct scsi_qla_host *ha)
{
scsi_lu_t *q;
int bus, target, lun;
ENTER("qla1280_restart_queues");
for (bus = 0; bus < ha->ports; bus++)
for (target = 0; target < MAX_TARGETS; target++)
for (lun = 0; lun < MAX_LUNS; lun++) {
q = LU_Q(ha, bus, target, lun);
if (q != NULL) {
if (q->q_first)
qla1280_next(ha, q, bus);
}
}
dprintk(3, "qla1280_restart_queues: exiting normally\n");
}
/*
* qla1280_abort_queue_single
* Abort all commands on a device queues.
*
* Input:
* ha = adapter block pointer.
*/
static void
qla1280_abort_queue_single(struct scsi_qla_host *ha, int bus,
int target, int lun, uint32_t stat)
{
scsi_lu_t *q;
srb_t *sp, *sp_next;
ENTER("qla1280_abort_queue_single");
q = LU_Q(ha, bus, target, lun);
if (q != NULL) {
sp = q->q_first;
q->q_first = q->q_last = NULL;
while (sp) {
sp_next = sp->s_next;
CMD_RESULT(sp->cmd) = stat;
qla1280_done_q_put(sp, &ha->done_q_first,
&ha->done_q_last);
sp = sp_next;
}
}
LEAVE("qla1280_abort_queue_single");
}
/*
* qla1280_abort_queues
* Abort all commands on device queues.
*
* Input:
* ha = adapter block pointer.
*/
static void
qla1280_abort_queues(struct scsi_qla_host *ha)
{
uint32_t bus, target, lun;
ENTER("qla1280_abort_queues");
for (bus = 0; bus < ha->ports; bus++)
for (target = 0; target < MAX_TARGETS; target++)
for (lun = 0; lun < MAX_LUNS; lun++)
qla1280_abort_queue_single(ha, bus, target,
lun, DID_RESET);
LEAVE("qla1280_abort_queues");
}
/*
* qla1280_debounce_register
* Debounce register.
*
* Input:
* port = register address.
*
* Returns:
* register value.
*/
static u16
qla1280_debounce_register(volatile u16 * addr)
{
volatile u16 ret;
volatile u16 ret2;
ret = RD_REG_WORD(addr);
ret2 = RD_REG_WORD(addr);
if (ret == ret2)
return ret;
do {
cpu_relax();
ret = RD_REG_WORD(addr);
ret2 = RD_REG_WORD(addr);
} while (ret != ret2);
return ret;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
#ifdef MODULE
Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE;
#include "scsi_module.c"
#endif
#else /* new kernel scsi initialization scheme */
static Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE;
#include "scsi_module.c"
#endif
/************************************************************************
* qla1280_check_for_dead_scsi_bus *
* *
* This routine checks for a dead SCSI bus *
************************************************************************/
#define SET_SXP_BANK 0x0100
#define SCSI_PHASE_INVALID 0x87FF
static int
qla1280_check_for_dead_scsi_bus(struct scsi_qla_host *ha, unsigned int bus)
{
uint16_t config_reg, scsi_control;
struct device_reg *reg = ha->iobase;
#if 0
unsigned int bus;
Scsi_Cmnd *cp;
/*
* If SCSI Bus is Dead because of bad termination,
* we will return a status of Selection timeout.
*/
cp = sp->cmd;
bus = SCSI_BUS_32(cp);
#endif
if (ha->bus_settings[bus].scsi_bus_dead) {
WRT_REG_WORD(&reg->host_cmd, HC_PAUSE_RISC);
config_reg = RD_REG_WORD(&reg->cfg_1);
WRT_REG_WORD(&reg->cfg_1, SET_SXP_BANK);
scsi_control = RD_REG_WORD(&reg->scsiControlPins);
WRT_REG_WORD(&reg->cfg_1, config_reg);
WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
if (scsi_control == SCSI_PHASE_INVALID) {
ha->bus_settings[bus].scsi_bus_dead = TRUE;
#if 0
CMD_RESULT(cp) = DID_NO_CONNECT << 16;
CMD_HANDLE(cp) = NULL;
/* ha->actthreads--; */
(*(cp)->scsi_done)(cp);
#endif
return TRUE; /* bus is dead */
} else {
ha->bus_settings[bus].scsi_bus_dead = FALSE;
ha->bus_settings[bus].failed_reset_count = 0;
}
}
return FALSE; /* bus is not dead */
}
static void
qla12160_get_target_parameters(struct scsi_qla_host *ha, uint32_t bus,
uint32_t target, uint32_t lun)
{
uint16_t mb[MAILBOX_REGISTER_COUNT];
mb[0] = MBC_GET_TARGET_PARAMETERS;
mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
mb[1] <<= 8;
qla1280_mailbox_command(ha, BIT_6 | BIT_3 | BIT_2 | BIT_1 | BIT_0,
&mb[0]);
if (mb[3] != 0) {
printk(KERN_INFO
"scsi(%ld:%d:%d:%d): Synchronous transfer at period "
"%d, offset %d. \n", ha->host_no, bus, target, lun,
(mb[3] & 0xff), (mb[3] >> 8));
}
if ((mb[2] & BIT_5) && ((mb[6] >> 8) & 0xff) >= 2) {
printk(KERN_INFO
"scsi(%ld:%d:%d:%d): Dual Transition enabled.\n",
ha->host_no, bus, target, lun);
}
}
#ifdef QL_DEBUG_ROUTINES
/****************************************************************************/
/* Driver Debug Functions. */
/****************************************************************************/
/*
* Get byte from I/O port
*/
static u8
qla1280_getbyte (u8 * port)
{
u8 ret;
#if MEMORY_MAPPED_IO
ret = readb((unsigned long) port);
#else
ret = inb((unsigned long) port);
#endif
if (ql_debug_print)
printk(KERN_DEBUG
"qla1280_getbyte: address = 0x%p, data = 0x%x", port,
ret);
return ret;
}
/*
* Get word from I/O port
*/
static u16
qla1280_getword (u16 * port)
{
u16 ret;
#if MEMORY_MAPPED_IO
ret = readw(unsigned long) port;
#else
ret = inw((unsigned long) port);
#endif
if (ql_debug_print)
printk(KERN_DEBUG
"qla1280_getbyte: address = 0x%p, data = 0x%x", port,
ret);
return ret;
}
/*
* Get double word from I/O port
*/
static u32
qla1280_getdword (u32 * port)
{
u32 ret;
#if MEMORY_MAPPED_IO
ret = readl((unsigned long) port);
#else
ret = inl((unsigned long) port);
#endif
if (ql_debug_print)
printk(KERN_DEBUG
"qla1280_getbyte: address = 0x%p, data = 0x%x", port,
ret);
return ret;
}
/*
* Send byte to I/O port
*/
static void
qla1280_putbyte(u8 * port, u8 data)
{
#if MEMORY_MAPPED_IO
writeb(data, (unsigned long) port);
#else
outb(data, (unsigned long) port);
#endif
if (ql_debug_print)
printk(KERN_DEBUG
"qla1280_getbyte: address = 0x%p, data = 0x%x", port,
data);
}
/*
* Send word to I/O port
*/
static void
qla1280_putword(u16 * port, u16 data)
{
#if MEMORY_MAPPED_IO
writew(data, (unsigned long) port);
#else
outw(data, (unsigned long) port);
#endif
if (ql_debug_print)
printk(KERN_DEBUG
"qla1280_getbyte: address = 0x%p, data = 0x%x", port,
data);
}
/*
* Send double word to I/O port
*/
static void
qla1280_putdword(u32 * port, u32 data)
{
#if MEMORY_MAPPED_IO
writel(data, (unsigned long) port);
#else
outl(data, (unsigned long) port);
#endif
if (ql_debug_print)
printk(KERN_DEBUG
"qla1280_getbyte: address = 0x%p, data = 0x%x", port,
data);
}
/*
* Dummy function to prevent warnings for
* declared and unused debug functions
*/
static void
qla1280_debug(void)
{
qla1280_getbyte(0);
qla1280_getword(0);
qla1280_getdword(0);
qla1280_putbyte(0, 0);
qla1280_putword(0, 0);
qla1280_putdword(0, 0);
}
static void
__qla1280_dump_buffer(char *b, int size)
{
int cnt;
u8 c;
if (ql_debug_print) {
printk(KERN_DEBUG
" 0 1 2 3 4 5 6 7 8 9 Ah "
"Bh Ch Dh Eh Fh\n");
printk(KERN_DEBUG
"---------------------------------------------"
"------------------\n");
for (cnt = 0; cnt < size;) {
c = *b++;
if (c < 16)
printk(' ');
printk("0x%x", c);
cnt++;
if (!(cnt % 16))
printk("\n");
else if (c < 10)
printk(" ");
else
printk(' ');
}
if (cnt % 16)
printk("\n");
}
}
/**************************************************************************
* ql1280_print_scsi_cmd
*
**************************************************************************/
static void
qla1280_print_scsi_cmd(Scsi_Cmnd * cmd)
{
struct scsi_qla_host *ha;
struct Scsi_Host *host = cmd->host;
srb_t *sp;
/* struct scatterlist *sg; */
int i;
ha = (struct scsi_qla_host *)host->hostdata;
sp = (srb_t *)CMD_SP(cmd);
printk("SCSI Command @= 0x%p, Handle=0x%p\n", cmd, CMD_HANDLE(cmd));
printk(" chan=%d, target = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n",
cmd->channel, cmd->target, cmd->lun, cmd->cmd_len);
printk(" CDB = ");
for (i = 0; i < cmd->cmd_len; i++) {
printk("0x%02x ", cmd->cmnd[i]);
}
printk(" seg_cnt =%d\n", cmd->use_sg);
printk(" request buffer=0x%p, request buffer len=0x%x\n",
cmd->request_buffer, cmd->request_bufflen);
/* if (cmd->use_sg)
{
sg = (struct scatterlist *) cmd->request_buffer;
printk(" SG buffer: \n");
qla1280_dump_buffer(1, (char *)sg, (cmd->use_sg*sizeof(struct scatterlist)));
} */
printk(" tag=%d, flags=0x%x, transfersize=0x%x \n",
cmd->tag, cmd->flags, cmd->transfersize);
printk(" Pid=%li, SP=0x%p\n", cmd->pid, CMD_SP(cmd));
printk(" underflow size = 0x%x, direction=0x%x, req.cmd=0x%x \n",
cmd->underflow, sp->dir, cmd->request->cmd);
}
/**************************************************************************
* ql1280_dump_device
*
**************************************************************************/
void
ql1280_dump_device(struct scsi_qla_host *ha)
{
Scsi_Cmnd *cp;
srb_t *sp;
int i;
if (ql_debug_print) {
printk(KERN_DEBUG "Outstanding Commands on controller:\n");
for (i = 0; i < MAX_OUTSTANDING_COMMANDS; i++) {
if ((sp = ha->outstanding_cmds[i]) == NULL)
continue;
if ((cp = sp->cmd) == NULL)
continue;
qla1280_print_scsi_cmd(1, cp);
}
}
}
#endif
#if STOP_ON_ERROR
/**************************************************************************
* ql1280_panic
*
**************************************************************************/
static void
qla1280_panic(char *cp, struct Scsi_Host *host)
{
struct scsi_qla_host *ha;
long *fp;
ha = (struct scsi_qla_host *)host->hostdata;
printk(KERN_ERR "qla1280 - PANIC: %s\n", cp);
printk(KERN_ERR "Current time=0x%lx\n", jiffies);
printk(KERN_ERR "Number of pending commands =0x%lx\n", ha->actthreads);
printk(KERN_ERR "Number of SCSI queued commands =0x%lx\n",
ha->qthreads);
printk(KERN_ERR "Number of free entries = (%d)\n", ha->req_q_cnt);
printk(KERN_ERR "Request Queue @ 0x%lx, Response Queue @ 0x%lx\n",
ha->request_dma, ha->response_dma);
printk(KERN_ERR "Request In Ptr %d\n", ha->req_ring_index);
fp = (long *) &ha->flags;
printk(KERN_ERR "HA flags =0x%lx\n", *fp);
if (ql_debug_level >= 2) {
ql_debug_print = 1;
#if 0
ql1280_dump_device((struct scsi_qla_host *)host->hostdata);
#endif
}
sti();
panic("Ooops");
/* cli();
for(;;)
{
barrier();
sti();
}
*/
}
#endif
#ifdef MODULE
/**************************************************************************
* qla1280_setup
*
* Handle Linux boot parameters. This routine allows for assigning a value
* to a parameter with a ':' between the parameter and the value.
* ie. qla1280=max_reqs:0x0A,verbose
**************************************************************************/
void
qla1280_setup(char *s, int *dummy)
{
char *end, *str, *cp;
printk(KERN_INFO "scsi: Processing Option str = %s\n", s);
end = strchr (s, '\0');
/* locate command */
str = s;
for (cp = s; *cp && cp != end; cp++) {
cp = qla1280_get_token(cp, str);
printk(KERN_INFO "scsi: token str = %s\n", str);
/* if found execute routine */
}
}
static char *
qla1280_get_token(char *cmdline, char *str)
{
register char *cp = cmdline;
/* skip preceeding spaces */
while (strchr (cp, ' '))
++cp;
/* symbol starts here */
str = cp;
/* skip char if not a space or : */
while (*cp && !(strchr (cp, ' ') || strchr (cp, ':')))
cp++;
*cp = '\0';
return cp;
}
#endif
/*
* Overrides for Emacs so that we almost follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-basic-offset: 8
* tab-width: 8
* End:
*/