Commit 473c67f9 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by James Bottomley

[PATCH] sym2 version 2.2.0

Docs
 - The sym53c8xx= kernel parameter no longer exists
 - Correct a typo

Bugfixes
 - The driver really isn't capable of dealing with 64-bit bus addresses
   yet, so bail out early
 - Get rid of SYM_SCAN_TARGETS_HILO (which had no effect) and set the
   shost->reverse_ordering flag instead
 - Associate a scsi_device with the target in slave_alloc instead of
   slave_configure

Printk cleanups
 - Use dev_warn/dev_info where possible
 - Delete PRINT_ADDR, PRINT_TARGET and PRINT_LUN
 - Remove sym_print_target() and sym_print_lun()
 - Make sym_print_addr() call dev_info

Memory allocation related
 - Delete non-dma allocators; use kmalloc/kcalloc directly instead
 - Move memory allocation wrappers from sym_glue to sym_malloc
 - Get rid of m_addr_t; use void * or dma_addr_t as appropriate
 - Change m_pool_ident_t from a struct pci_dev * to a struct device *
 - Use dma_alloc_coherent() instead of pci_alloc_consistent()

Negotiation related
 - Move scsi_transport_spi.h include from sym_glue.c to sym_glue.h
 - Store the current transfer contract settings in the starget attributes
 - Delete sym2_get_offset(), sym2_get_period(), sym2_get_width(),
   sym2_get_dt(), sym2_get_iu() and sym2_get_qas()
 - Use spi_support_wide() (and friends) instead of scsi_device_wide()
 - We don't need tinfo.prev -- we can tell if the contract changed
 - Delete SYM_OPT_ANNOUNCE_TRANSFER_RATE
 - Use spi_display_xfer_agreement()
 - Use sdev->scsi_level instead of the never-set tinfo.curr.scsi_version
 - Instead of checking current xfer settings against our goal, use a
   check_nego flag.
 - Get rid of sym_tinfo and use sym_trans directly.
 - Split the sym_trans options into flags
 - Change width from an u8 into a flag
 - Delete sym_misc.c
 - Remove sym_xpt_async_nego_wide

Linuxisation
 - Use udelay() directly instead of indirecting through UDELAY and sym_udelay
 - Rename some scsi_cmnd pointers from ccb or csio to cmd
 - Use simple_strtoul() instead of a handwritten parser
 - SKIP_SPACES was always being used with 1 as a parameter, and was implicitly
   modifying ptr and len.
 - GET_INT_ARG was doing the same with ptr and len.
 - Use pci_iomap(), pci_iounmap(), ioread8() et al
 - Delete the sym_data_dmamap_*() macros
 - Replace SYM_CONF_IOMAPPED with CONFIG_SCSI_SYM53C8XX_IOMAPPED
 - Delete unused SYM_HAVE_SCCB, SYM_HAVE_M_SVTOB, SYM_HAVE_M_SPOOL

Misc cleanup
 - Move sym_conf.h into sym53c8xx.h
 - Eliminate the unused SYM_SETUP_MAX_LUN, SYM_SCMD_PTR
 - SYM_SETUP_PCI_PARITY and SYM_SETUP_SCSI_PARITY are always defined; simplify
 - Rename sym_pci_chip to sym_chip
 - Write sym_get_hcb() to hide nasty macro abuse
 - sym_lp() doesn't need to take the sym_hcb as an argument
 - sym_get_ccb() works better if you give it the cmd instead of the id/lun
 - We don't use cmd->host_scribble, host->dma_channel, host->n_io_port,
   host->io_port, host->base or host->irq; stop initialising them.
 - sym_tune_dev_queuing() works better if you give it the tcb rather than
   the hcb and target
 - Get rid of sym_driver_name(), just use SYM_DRIVER_NAME directly
 - OUTB/INB/etc macros implicitly use the hcb pointer; pass it explictly instead
 - Map the BARs early instead of mapping and unmapping them as necessary
 - Automatically fall back to ioport accesses if iomem isn't available
 - Get rid of tcb_p, lcb_p and ccb_p typedefs
 - Delete support for big endian chips -- 8xx chips can't be in BE mode
 - Inline sym_slot into sym_device
 - Inline sym_printb_hex() into sym_printl_hex()
 - Don't cast function return values to void
 - Introduce sym_nvram_type()
 - Pass the hcb and starget to sym_check_goals since we already have them
   in the caller
 - Some 0/NULL cleanup
 - Embed the sense buffer in the CCB so it doesn't need to be allocated
   separately
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent cee9a2d6
...@@ -1345,9 +1345,6 @@ running once the system is up. ...@@ -1345,9 +1345,6 @@ running once the system is up.
sym53c416= [HW,SCSI] sym53c416= [HW,SCSI]
See header of drivers/scsi/sym53c416.c. See header of drivers/scsi/sym53c416.c.
sym53c8xx= [HW,SCSI]
See Documentation/scsi/ncr53c8xx.txt.
t128= [HW,SCSI] t128= [HW,SCSI]
See header of drivers/scsi/t128.c. See header of drivers/scsi/t128.c.
......
...@@ -440,7 +440,7 @@ lilo: linux root=/dev/sda2 sym53c8xx.cmd_per_lun=4 sym53c8xx.sync=10 sym53c8xx.d ...@@ -440,7 +440,7 @@ lilo: linux root=/dev/sda2 sym53c8xx.cmd_per_lun=4 sym53c8xx.sync=10 sym53c8xx.d
The following command will install the driver module with the same The following command will install the driver module with the same
options as above. options as above.
modprobe sym53c8xx cmd_per_lun=4 sync=10 debug=0x200" modprobe sym53c8xx cmd_per_lun=4 sync=10 debug=0x200
10.2 Available arguments 10.2 Available arguments
......
# Makefile for the NCR/SYMBIOS/LSI 53C8XX PCI SCSI controllers driver. # Makefile for the NCR/SYMBIOS/LSI 53C8XX PCI SCSI controllers driver.
sym53c8xx-objs := sym_fw.o sym_glue.o sym_hipd.o sym_malloc.o sym_misc.o sym_nvram.o sym53c8xx-objs := sym_fw.o sym_glue.o sym_hipd.o sym_malloc.o sym_nvram.o
obj-$(CONFIG_SCSI_SYM53C8XX_2) := sym53c8xx.o obj-$(CONFIG_SCSI_SYM53C8XX_2) := sym53c8xx.o
...@@ -42,10 +42,6 @@ ...@@ -42,10 +42,6 @@
#include <linux/config.h> #include <linux/config.h>
#ifdef CONFIG_SCSI_SYM53C8XX_IOMAPPED
#define SYM_CONF_IOMAPPED
#endif
/* /*
* DMA addressing mode. * DMA addressing mode.
* *
...@@ -144,10 +140,6 @@ struct sym_driver_setup { ...@@ -144,10 +140,6 @@ struct sym_driver_setup {
#define SYM_SETUP_HOST_ID sym_driver_setup.host_id #define SYM_SETUP_HOST_ID sym_driver_setup.host_id
#define boot_verbose sym_driver_setup.verbose #define boot_verbose sym_driver_setup.verbose
/* Always enable parity. */
#define SYM_SETUP_PCI_PARITY 1
#define SYM_SETUP_SCSI_PARITY 1
/* /*
* Initial setup. * Initial setup.
* *
...@@ -170,4 +162,56 @@ extern struct sym_driver_setup sym_driver_setup; ...@@ -170,4 +162,56 @@ extern struct sym_driver_setup sym_driver_setup;
extern unsigned int sym_debug_flags; extern unsigned int sym_debug_flags;
#define DEBUG_FLAGS sym_debug_flags #define DEBUG_FLAGS sym_debug_flags
/*
* Max number of targets.
* Maximum is 16 and you are advised not to change this value.
*/
#ifndef SYM_CONF_MAX_TARGET
#define SYM_CONF_MAX_TARGET (16)
#endif
/*
* Max number of logical units.
* SPI-2 allows up to 64 logical units, but in real life, target
* that implements more that 7 logical units are pretty rare.
* Anyway, the cost of accepting up to 64 logical unit is low in
* this driver, thus going with the maximum is acceptable.
*/
#ifndef SYM_CONF_MAX_LUN
#define SYM_CONF_MAX_LUN (64)
#endif
/*
* Max number of IO control blocks queued to the controller.
* Each entry needs 8 bytes and the queues are allocated contiguously.
* Since we donnot want to allocate more than a page, the theorical
* maximum is PAGE_SIZE/8. For safety, we announce a bit less to the
* access method. :)
* When not supplied, as it is suggested, the driver compute some
* good value for this parameter.
*/
/* #define SYM_CONF_MAX_START (PAGE_SIZE/8 - 16) */
/*
* Support for Immediate Arbitration.
* Not advised.
*/
/* #define SYM_CONF_IARB_SUPPORT */
/*
* Only relevant if IARB support configured.
* - Max number of successive settings of IARB hints.
* - Set IARB on arbitration lost.
*/
#define SYM_CONF_IARB_MAX 3
#define SYM_CONF_SET_IARB_ON_ARB_LOST 1
/*
* Returning wrong residuals may make problems.
* When zero, this define tells the driver to
* always return 0 as transfer residual.
* Btw, all my testings of residuals have succeeded.
*/
#define SYM_SETUP_RESIDUAL_SUPPORT 1
#endif /* SYM53C8XX_H */ #endif /* SYM53C8XX_H */
/*
* Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family
* of PCI-SCSI IO processors.
*
* Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr>
*
* This driver is derived from the Linux sym53c8xx driver.
* Copyright (C) 1998-2000 Gerard Roudier
*
* The sym53c8xx driver is derived from the ncr53c8xx driver that had been
* a port of the FreeBSD ncr driver to Linux-1.2.13.
*
* The original ncr driver has been written for 386bsd and FreeBSD by
* Wolfgang Stanglmeier <wolf@cologne.de>
* Stefan Esser <se@mi.Uni-Koeln.de>
* Copyright (C) 1994 Wolfgang Stanglmeier
*
* Other major contributions:
*
* NVRAM detection and reading.
* Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
*
*-----------------------------------------------------------------------------
*
* 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 of the License, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef SYM_CONF_H
#define SYM_CONF_H
#include "sym53c8xx.h"
/*
* Max number of targets.
* Maximum is 16 and you are advised not to change this value.
*/
#ifndef SYM_CONF_MAX_TARGET
#define SYM_CONF_MAX_TARGET (16)
#endif
/*
* Max number of logical units.
* SPI-2 allows up to 64 logical units, but in real life, target
* that implements more that 7 logical units are pretty rare.
* Anyway, the cost of accepting up to 64 logical unit is low in
* this driver, thus going with the maximum is acceptable.
*/
#ifndef SYM_CONF_MAX_LUN
#define SYM_CONF_MAX_LUN (64)
#endif
/*
* Max number of IO control blocks queued to the controller.
* Each entry needs 8 bytes and the queues are allocated contiguously.
* Since we donnot want to allocate more than a page, the theorical
* maximum is PAGE_SIZE/8. For safety, we announce a bit less to the
* access method. :)
* When not supplied, as it is suggested, the driver compute some
* good value for this parameter.
*/
/* #define SYM_CONF_MAX_START (PAGE_SIZE/8 - 16) */
/*
* Support for Immediate Arbitration.
* Not advised.
*/
/* #define SYM_CONF_IARB_SUPPORT */
/*
* Only relevant if IARB support configured.
* - Max number of successive settings of IARB hints.
* - Set IARB on arbitration lost.
*/
#define SYM_CONF_IARB_MAX 3
#define SYM_CONF_SET_IARB_ON_ARB_LOST 1
/*
* Returning wrong residuals may make problems.
* When zero, this define tells the driver to
* always return 0 as transfer residual.
* Btw, all my testings of residuals have succeeded.
*/
#define SYM_SETUP_RESIDUAL_SUPPORT 1
/*
* Supported maximum number of LUNs to announce to
* the access method.
* The driver supports up to 64 LUNs per target as
* required by SPI-2/SPI-3. However some SCSI devices
* designed prior to these specifications or not being
* conformant may be highly confused when they are
* asked about a LUN > 7.
*/
#ifndef SYM_SETUP_MAX_LUN
#define SYM_SETUP_MAX_LUN (8)
#endif
#endif /* SYM_CONF_H */
...@@ -40,13 +40,13 @@ ...@@ -40,13 +40,13 @@
#ifndef SYM_DEFS_H #ifndef SYM_DEFS_H
#define SYM_DEFS_H #define SYM_DEFS_H
#define SYM_VERSION "2.1.18n" #define SYM_VERSION "2.2.0"
#define SYM_DRIVER_NAME "sym-" SYM_VERSION #define SYM_DRIVER_NAME "sym-" SYM_VERSION
/* /*
* SYM53C8XX device features descriptor. * SYM53C8XX device features descriptor.
*/ */
struct sym_pci_chip { struct sym_chip {
u_short device_id; u_short device_id;
u_short revision_id; u_short revision_id;
char *name; char *name;
......
...@@ -361,7 +361,7 @@ static struct sym_fw sym_fw2 = SYM_FW_ENTRY(sym_fw2, "LOAD/STORE-based"); ...@@ -361,7 +361,7 @@ static struct sym_fw sym_fw2 = SYM_FW_ENTRY(sym_fw2, "LOAD/STORE-based");
* Find the most appropriate firmware for a chip. * Find the most appropriate firmware for a chip.
*/ */
struct sym_fw * struct sym_fw *
sym_find_firmware(struct sym_pci_chip *chip) sym_find_firmware(struct sym_chip *chip)
{ {
if (chip->features & FE_LDSTR) if (chip->features & FE_LDSTR)
return &sym_fw2; return &sym_fw2;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* of PCI-SCSI IO processors. * of PCI-SCSI IO processors.
* *
* Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr> * Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr>
* Copyright (c) 2003-2004 Matthew Wilcox <matthew@wil.cx> * Copyright (c) 2003-2005 Matthew Wilcox <matthew@wil.cx>
* *
* This driver is derived from the Linux sym53c8xx driver. * This driver is derived from the Linux sym53c8xx driver.
* Copyright (C) 1998-2000 Gerard Roudier * Copyright (C) 1998-2000 Gerard Roudier
...@@ -47,7 +47,6 @@ ...@@ -47,7 +47,6 @@
#include <scsi/scsi_tcq.h> #include <scsi/scsi_tcq.h>
#include <scsi/scsi_device.h> #include <scsi/scsi_device.h>
#include <scsi/scsi_transport.h> #include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
#include "sym_glue.h" #include "sym_glue.h"
#include "sym_nvram.h" #include "sym_nvram.h"
...@@ -135,80 +134,46 @@ static void sym2_setup_params(void) ...@@ -135,80 +134,46 @@ static void sym2_setup_params(void)
} }
} }
/*
* We used to try to deal with 64-bit BARs here, but don't any more.
* There are many parts of this driver which would need to be modified
* to handle a 64-bit base address, including scripts. I'm uncomfortable
* with making those changes when I have no way of testing it, so I'm
* just going to disable it.
*
* Note that some machines (eg HP rx8620 and Superdome) have bus addresses
* below 4GB and physical addresses above 4GB. These will continue to work.
*/
static int __devinit static int __devinit
pci_get_base_address(struct pci_dev *pdev, int index, u_long *base) pci_get_base_address(struct pci_dev *pdev, int index, unsigned long *basep)
{ {
u32 tmp; u32 tmp;
unsigned long base;
#define PCI_BAR_OFFSET(index) (PCI_BASE_ADDRESS_0 + (index<<2)) #define PCI_BAR_OFFSET(index) (PCI_BASE_ADDRESS_0 + (index<<2))
pci_read_config_dword(pdev, PCI_BAR_OFFSET(index), &tmp); pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp);
*base = tmp; base = tmp;
++index;
if ((tmp & 0x7) == PCI_BASE_ADDRESS_MEM_TYPE_64) { if ((tmp & 0x7) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
#if BITS_PER_LONG > 32 pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp);
pci_read_config_dword(pdev, PCI_BAR_OFFSET(index), &tmp); if (tmp > 0)
*base |= (((u_long)tmp) << 32); dev_err(&pdev->dev,
#endif "BAR %d is 64-bit, disabling\n", index - 1);
++index; base = 0;
} }
if ((base & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
base &= PCI_BASE_ADDRESS_IO_MASK;
} else {
base &= PCI_BASE_ADDRESS_MEM_MASK;
}
*basep = base;
return index; return index;
#undef PCI_BAR_OFFSET #undef PCI_BAR_OFFSET
} }
/* This lock protects only the memory allocation/free. */
static DEFINE_SPINLOCK(sym53c8xx_lock);
static struct scsi_transport_template *sym2_transport_template = NULL; static struct scsi_transport_template *sym2_transport_template = NULL;
/*
* Wrappers to the generic memory allocator.
*/
void *sym_calloc(int size, char *name)
{
unsigned long flags;
void *m;
spin_lock_irqsave(&sym53c8xx_lock, flags);
m = sym_calloc_unlocked(size, name);
spin_unlock_irqrestore(&sym53c8xx_lock, flags);
return m;
}
void sym_mfree(void *m, int size, char *name)
{
unsigned long flags;
spin_lock_irqsave(&sym53c8xx_lock, flags);
sym_mfree_unlocked(m, size, name);
spin_unlock_irqrestore(&sym53c8xx_lock, flags);
}
void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name)
{
unsigned long flags;
void *m;
spin_lock_irqsave(&sym53c8xx_lock, flags);
m = __sym_calloc_dma_unlocked(dev_dmat, size, name);
spin_unlock_irqrestore(&sym53c8xx_lock, flags);
return m;
}
void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name)
{
unsigned long flags;
spin_lock_irqsave(&sym53c8xx_lock, flags);
__sym_mfree_dma_unlocked(dev_dmat, m, size, name);
spin_unlock_irqrestore(&sym53c8xx_lock, flags);
}
m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m)
{
unsigned long flags;
m_addr_t b;
spin_lock_irqsave(&sym53c8xx_lock, flags);
b = __vtobus_unlocked(dev_dmat, m);
spin_unlock_irqrestore(&sym53c8xx_lock, flags);
return b;
}
/* /*
* Used by the eh thread to wait for command completion. * Used by the eh thread to wait for command completion.
* It is allocated on the eh thread stack. * It is allocated on the eh thread stack.
...@@ -231,8 +196,7 @@ struct sym_ucmd { /* Override the SCSI pointer structure */ ...@@ -231,8 +196,7 @@ struct sym_ucmd { /* Override the SCSI pointer structure */
}; };
#define SYM_UCMD_PTR(cmd) ((struct sym_ucmd *)(&(cmd)->SCp)) #define SYM_UCMD_PTR(cmd) ((struct sym_ucmd *)(&(cmd)->SCp))
#define SYM_SCMD_PTR(ucmd) sym_que_entry(ucmd, struct scsi_cmnd, SCp) #define SYM_SOFTC_PTR(cmd) sym_get_hcb(cmd->device->host)
#define SYM_SOFTC_PTR(cmd) (((struct host_data *)cmd->device->host->hostdata)->ncb)
static void __unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) static void __unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
{ {
...@@ -288,30 +252,19 @@ static int __map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) ...@@ -288,30 +252,19 @@ static int __map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
/* /*
* Complete a pending CAM CCB. * Complete a pending CAM CCB.
*/ */
void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb) void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *cmd)
{ {
unmap_scsi_data(np, ccb); unmap_scsi_data(np, cmd);
ccb->scsi_done(ccb); cmd->scsi_done(cmd);
} }
static void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *ccb, int cam_status) static void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *cmd, int cam_status)
{ {
sym_set_cam_status(ccb, cam_status); sym_set_cam_status(cmd, cam_status);
sym_xpt_done(np, ccb); sym_xpt_done(np, cmd);
} }
/*
* Print something that identifies the IO.
*/
void sym_print_addr(struct sym_ccb *cp)
{
struct scsi_cmnd *cmd = cp->cam_ccb;
if (cmd)
printf("%s:%d:%d:", sym_name(SYM_SOFTC_PTR(cmd)),
cmd->device->id, cmd->device->lun);
}
/* /*
* Tell the SCSI layer about a BUS RESET. * Tell the SCSI layer about a BUS RESET.
*/ */
...@@ -333,16 +286,6 @@ void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target) ...@@ -333,16 +286,6 @@ void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target)
printf_notice("%s: TARGET %d has been reset.\n", sym_name(np), target); printf_notice("%s: TARGET %d has been reset.\n", sym_name(np), target);
} }
/*
* Tell the SCSI layer about the new transfer parameters.
*/
void sym_xpt_async_nego_wide(struct sym_hcb *np, int target)
{
if (sym_verbose < 3)
return;
sym_announce_transfer_rate(np, target);
}
/* /*
* Choose the more appropriate CAM status if * Choose the more appropriate CAM status if
* the IO encountered an extended error. * the IO encountered an extended error.
...@@ -367,7 +310,7 @@ static int sym_xerr_cam_status(int cam_status, int x_status) ...@@ -367,7 +310,7 @@ static int sym_xerr_cam_status(int cam_status, int x_status)
*/ */
void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid) void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
{ {
struct scsi_cmnd *csio = cp->cam_ccb; struct scsi_cmnd *cmd = cp->cmd;
u_int cam_status, scsi_status, drv_status; u_int cam_status, scsi_status, drv_status;
drv_status = 0; drv_status = 0;
...@@ -378,7 +321,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid) ...@@ -378,7 +321,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
scsi_status = cp->sv_scsi_status; scsi_status = cp->sv_scsi_status;
resid = cp->sv_resid; resid = cp->sv_resid;
if (sym_verbose && cp->sv_xerr_status) if (sym_verbose && cp->sv_xerr_status)
sym_print_xerr(cp, cp->sv_xerr_status); sym_print_xerr(cmd, cp->sv_xerr_status);
if (cp->host_status == HS_COMPLETE && if (cp->host_status == HS_COMPLETE &&
cp->ssss_status == S_GOOD && cp->ssss_status == S_GOOD &&
cp->xerr_status == 0) { cp->xerr_status == 0) {
...@@ -388,9 +331,9 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid) ...@@ -388,9 +331,9 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
/* /*
* Bounce back the sense data to user. * Bounce back the sense data to user.
*/ */
memset(&csio->sense_buffer, 0, sizeof(csio->sense_buffer)); memset(&cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
memcpy(csio->sense_buffer, cp->sns_bbuf, memcpy(cmd->sense_buffer, cp->sns_bbuf,
min(sizeof(csio->sense_buffer), min(sizeof(cmd->sense_buffer),
(size_t)SYM_SNS_BBUF_LEN)); (size_t)SYM_SNS_BBUF_LEN));
#if 0 #if 0
/* /*
...@@ -400,7 +343,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid) ...@@ -400,7 +343,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
*/ */
if (1) { if (1) {
u_char *p; u_char *p;
p = (u_char *) csio->sense_data; p = (u_char *) cmd->sense_data;
if (p[0]==0x70 && p[2]==0x6 && p[12]==0x29) if (p[0]==0x70 && p[2]==0x6 && p[12]==0x29)
sym_clear_tasks(np, DID_ABORT, sym_clear_tasks(np, DID_ABORT,
cp->target,cp->lun, -1); cp->target,cp->lun, -1);
...@@ -413,7 +356,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid) ...@@ -413,7 +356,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
* condition otherwise the device will always return * condition otherwise the device will always return
* BUSY. Use a big stick. * BUSY. Use a big stick.
*/ */
sym_reset_scsi_target(np, csio->device->id); sym_reset_scsi_target(np, cmd->device->id);
cam_status = DID_ERROR; cam_status = DID_ERROR;
} }
} else if (cp->host_status == HS_COMPLETE) /* Bad SCSI status */ } else if (cp->host_status == HS_COMPLETE) /* Bad SCSI status */
...@@ -424,8 +367,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid) ...@@ -424,8 +367,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
cam_status = DID_ERROR; cam_status = DID_ERROR;
else { /* Extended error */ else { /* Extended error */
if (sym_verbose) { if (sym_verbose) {
PRINT_ADDR(cp); sym_print_addr(cmd, "COMMAND FAILED (%x %x %x).\n",
printf ("COMMAND FAILED (%x %x %x).\n",
cp->host_status, cp->ssss_status, cp->host_status, cp->ssss_status,
cp->xerr_status); cp->xerr_status);
} }
...@@ -434,8 +376,8 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid) ...@@ -434,8 +376,8 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
*/ */
cam_status = sym_xerr_cam_status(DID_ERROR, cp->xerr_status); cam_status = sym_xerr_cam_status(DID_ERROR, cp->xerr_status);
} }
csio->resid = resid; cmd->resid = resid;
csio->result = (drv_status << 24) + (cam_status << 16) + scsi_status; cmd->result = (drv_status << 24) + (cam_status << 16) + scsi_status;
} }
...@@ -502,9 +444,9 @@ static int sym_scatter(struct sym_hcb *np, struct sym_ccb *cp, struct scsi_cmnd ...@@ -502,9 +444,9 @@ static int sym_scatter(struct sym_hcb *np, struct sym_ccb *cp, struct scsi_cmnd
/* /*
* Queue a SCSI command. * Queue a SCSI command.
*/ */
static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb) static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *cmd)
{ {
/* struct scsi_device *device = ccb->device; */ struct scsi_device *sdev = cmd->device;
struct sym_tcb *tp; struct sym_tcb *tp;
struct sym_lcb *lp; struct sym_lcb *lp;
struct sym_ccb *cp; struct sym_ccb *cp;
...@@ -514,17 +456,17 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb) ...@@ -514,17 +456,17 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb)
* Minimal checkings, so that we will not * Minimal checkings, so that we will not
* go outside our tables. * go outside our tables.
*/ */
if (ccb->device->id == np->myaddr || if (sdev->id == np->myaddr ||
ccb->device->id >= SYM_CONF_MAX_TARGET || sdev->id >= SYM_CONF_MAX_TARGET ||
ccb->device->lun >= SYM_CONF_MAX_LUN) { sdev->lun >= SYM_CONF_MAX_LUN) {
sym_xpt_done2(np, ccb, CAM_DEV_NOT_THERE); sym_xpt_done2(np, cmd, CAM_DEV_NOT_THERE);
return 0; return 0;
} }
/* /*
* Retrieve the target descriptor. * Retrieve the target descriptor.
*/ */
tp = &np->target[ccb->device->id]; tp = &np->target[sdev->id];
/* /*
* Complete the 1st INQUIRY command with error * Complete the 1st INQUIRY command with error
...@@ -538,12 +480,12 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb) ...@@ -538,12 +480,12 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb)
* devices behave badly when asked for some non * devices behave badly when asked for some non
* zero LUN. Btw, this is an absolute hack.:-) * zero LUN. Btw, this is an absolute hack.:-)
*/ */
if (ccb->cmnd[0] == 0x12 || ccb->cmnd[0] == 0x0) { if (cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 0x0) {
if ((tp->usrflags & SYM_SCAN_BOOT_DISABLED) || if ((tp->usrflags & SYM_SCAN_BOOT_DISABLED) ||
((tp->usrflags & SYM_SCAN_LUNS_DISABLED) && ((tp->usrflags & SYM_SCAN_LUNS_DISABLED) &&
ccb->device->lun != 0)) { sdev->lun != 0)) {
tp->usrflags &= ~SYM_SCAN_BOOT_DISABLED; tp->usrflags &= ~SYM_SCAN_BOOT_DISABLED;
sym_xpt_done2(np, ccb, CAM_DEV_NOT_THERE); sym_xpt_done2(np, cmd, CAM_DEV_NOT_THERE);
return 0; return 0;
} }
} }
...@@ -551,23 +493,23 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb) ...@@ -551,23 +493,23 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb)
/* /*
* Select tagged/untagged. * Select tagged/untagged.
*/ */
lp = sym_lp(np, tp, ccb->device->lun); lp = sym_lp(tp, sdev->lun);
order = (lp && lp->s.reqtags) ? M_SIMPLE_TAG : 0; order = (lp && lp->s.reqtags) ? M_SIMPLE_TAG : 0;
/* /*
* Queue the SCSI IO. * Queue the SCSI IO.
*/ */
cp = sym_get_ccb(np, ccb->device->id, ccb->device->lun, order); cp = sym_get_ccb(np, cmd, order);
if (!cp) if (!cp)
return 1; /* Means resource shortage */ return 1; /* Means resource shortage */
sym_queue_scsiio(np, ccb, cp); sym_queue_scsiio(np, cmd, cp);
return 0; return 0;
} }
/* /*
* Setup buffers and pointers that address the CDB. * Setup buffers and pointers that address the CDB.
*/ */
static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *ccb, struct sym_ccb *cp) static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp)
{ {
u32 cmd_ba; u32 cmd_ba;
int cmd_len; int cmd_len;
...@@ -575,14 +517,14 @@ static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *ccb, struc ...@@ -575,14 +517,14 @@ static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *ccb, struc
/* /*
* CDB is 16 bytes max. * CDB is 16 bytes max.
*/ */
if (ccb->cmd_len > sizeof(cp->cdb_buf)) { if (cmd->cmd_len > sizeof(cp->cdb_buf)) {
sym_set_cam_status(cp->cam_ccb, CAM_REQ_INVALID); sym_set_cam_status(cp->cmd, CAM_REQ_INVALID);
return -1; return -1;
} }
memcpy(cp->cdb_buf, ccb->cmnd, ccb->cmd_len); memcpy(cp->cdb_buf, cmd->cmnd, cmd->cmd_len);
cmd_ba = CCB_BA (cp, cdb_buf[0]); cmd_ba = CCB_BA (cp, cdb_buf[0]);
cmd_len = ccb->cmd_len; cmd_len = cmd->cmd_len;
cp->phys.cmd.addr = cpu_to_scr(cmd_ba); cp->phys.cmd.addr = cpu_to_scr(cmd_ba);
cp->phys.cmd.size = cpu_to_scr(cmd_len); cp->phys.cmd.size = cpu_to_scr(cmd_len);
...@@ -593,29 +535,29 @@ static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *ccb, struc ...@@ -593,29 +535,29 @@ static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *ccb, struc
/* /*
* Setup pointers that address the data and start the I/O. * Setup pointers that address the data and start the I/O.
*/ */
int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp) int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp)
{ {
int dir; int dir;
struct sym_tcb *tp = &np->target[cp->target]; struct sym_tcb *tp = &np->target[cp->target];
struct sym_lcb *lp = sym_lp(np, tp, cp->lun); struct sym_lcb *lp = sym_lp(tp, cp->lun);
/* /*
* Build the CDB. * Build the CDB.
*/ */
if (sym_setup_cdb(np, csio, cp)) if (sym_setup_cdb(np, cmd, cp))
goto out_abort; goto out_abort;
/* /*
* No direction means no data. * No direction means no data.
*/ */
dir = csio->sc_data_direction; dir = cmd->sc_data_direction;
if (dir != DMA_NONE) { if (dir != DMA_NONE) {
cp->segments = sym_scatter(np, cp, csio); cp->segments = sym_scatter(np, cp, cmd);
if (cp->segments < 0) { if (cp->segments < 0) {
if (cp->segments == -2) if (cp->segments == -2)
sym_set_cam_status(csio, CAM_RESRC_UNAVAIL); sym_set_cam_status(cmd, CAM_RESRC_UNAVAIL);
else else
sym_set_cam_status(csio, CAM_REQ_TOO_BIG); sym_set_cam_status(cmd, CAM_REQ_TOO_BIG);
goto out_abort; goto out_abort;
} }
} else { } else {
...@@ -655,7 +597,7 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *csio, struct ...@@ -655,7 +597,7 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *csio, struct
out_abort: out_abort:
sym_free_ccb(np, cp); sym_free_ccb(np, cp);
sym_xpt_done(np, csio); sym_xpt_done(np, cmd);
return 0; return 0;
} }
...@@ -737,7 +679,6 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd, ...@@ -737,7 +679,6 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
int sts = 0; int sts = 0;
cmd->scsi_done = done; cmd->scsi_done = done;
cmd->host_scribble = NULL;
memset(ucp, 0, sizeof(*ucp)); memset(ucp, 0, sizeof(*ucp));
/* /*
...@@ -855,11 +796,8 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) ...@@ -855,11 +796,8 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
int to_do = SYM_EH_DO_IGNORE; int to_do = SYM_EH_DO_IGNORE;
int sts = -1; int sts = -1;
struct sym_eh_wait eh, *ep = &eh; struct sym_eh_wait eh, *ep = &eh;
char devname[20];
sprintf(devname, "%s:%d:%d", sym_name(np), cmd->device->id, cmd->device->lun);
printf_warning("%s: %s operation started.\n", devname, opname); dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname);
#if 0 #if 0
/* This one should be the result of some race, thus to ignore */ /* This one should be the result of some race, thus to ignore */
...@@ -870,7 +808,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) ...@@ -870,7 +808,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
/* This one is queued in some place -> to wait for completion */ /* This one is queued in some place -> to wait for completion */
FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) { FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq); struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
if (cp->cam_ccb == cmd) { if (cp->cmd == cmd) {
to_do = SYM_EH_DO_WAIT; to_do = SYM_EH_DO_WAIT;
goto prepare; goto prepare;
} }
...@@ -939,9 +877,9 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd) ...@@ -939,9 +877,9 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
if (ep->timed_out) if (ep->timed_out)
sts = -2; sts = -2;
} }
printf_warning("%s: %s operation %s.\n", devname, opname, dev_warn(&cmd->device->sdev_gendev, "%s operation %s.\n", opname,
sts==0?"complete":sts==-2?"timed-out":"failed"); sts==0 ? "complete" :sts==-2 ? "timed-out" : "failed");
return sts? SCSI_FAILED : SCSI_SUCCESS; return sts ? SCSI_FAILED : SCSI_SUCCESS;
} }
...@@ -971,10 +909,9 @@ static int sym53c8xx_eh_host_reset_handler(struct scsi_cmnd *cmd) ...@@ -971,10 +909,9 @@ static int sym53c8xx_eh_host_reset_handler(struct scsi_cmnd *cmd)
/* /*
* Tune device queuing depth, according to various limits. * Tune device queuing depth, according to various limits.
*/ */
static void sym_tune_dev_queuing(struct sym_hcb *np, int target, int lun, u_short reqtags) static void sym_tune_dev_queuing(struct sym_tcb *tp, int lun, u_short reqtags)
{ {
struct sym_tcb *tp = &np->target[target]; struct sym_lcb *lp = sym_lp(tp, lun);
struct sym_lcb *lp = sym_lp(np, tp, lun);
u_short oldtags; u_short oldtags;
if (!lp) if (!lp)
...@@ -990,9 +927,8 @@ static void sym_tune_dev_queuing(struct sym_hcb *np, int target, int lun, u_shor ...@@ -990,9 +927,8 @@ static void sym_tune_dev_queuing(struct sym_hcb *np, int target, int lun, u_shor
lp->s.reqtags = reqtags; lp->s.reqtags = reqtags;
if (reqtags != oldtags) { if (reqtags != oldtags) {
printf_info("%s:%d:%d: " dev_info(&tp->sdev->sdev_target->dev,
"tagged command queuing %s, command queue depth %d.\n", "tagged command queuing %s, command queue depth %d.\n",
sym_name(np), target, lun,
lp->s.reqtags ? "enabled" : "disabled", lp->s.reqtags ? "enabled" : "disabled",
lp->started_limit); lp->started_limit);
} }
...@@ -1051,21 +987,34 @@ static int device_queue_depth(struct sym_hcb *np, int target, int lun) ...@@ -1051,21 +987,34 @@ static int device_queue_depth(struct sym_hcb *np, int target, int lun)
return DEF_DEPTH; return DEF_DEPTH;
} }
static int sym53c8xx_slave_alloc(struct scsi_device *device)
{
struct sym_hcb *np = sym_get_hcb(device->host);
struct sym_tcb *tp = &np->target[device->id];
if (!tp->sdev)
tp->sdev = device;
return 0;
}
static void sym53c8xx_slave_destroy(struct scsi_device *device)
{
struct sym_hcb *np = sym_get_hcb(device->host);
struct sym_tcb *tp = &np->target[device->id];
if (tp->sdev == device)
tp->sdev = NULL;
}
/* /*
* Linux entry point for device queue sizing. * Linux entry point for device queue sizing.
*/ */
static int sym53c8xx_slave_configure(struct scsi_device *device) static int sym53c8xx_slave_configure(struct scsi_device *device)
{ {
struct Scsi_Host *host = device->host; struct sym_hcb *np = sym_get_hcb(device->host);
struct sym_hcb *np; struct sym_tcb *tp = &np->target[device->id];
struct sym_tcb *tp;
struct sym_lcb *lp; struct sym_lcb *lp;
int reqtags, depth_to_use; int reqtags, depth_to_use;
np = ((struct host_data *) host->hostdata)->ncb;
tp = &np->target[device->id];
tp->sdev = device;
/* /*
* Allocate the LCB if not yet. * Allocate the LCB if not yet.
* If it fail, we may well be in the sh*t. :) * If it fail, we may well be in the sh*t. :)
...@@ -1102,7 +1051,7 @@ static int sym53c8xx_slave_configure(struct scsi_device *device) ...@@ -1102,7 +1051,7 @@ static int sym53c8xx_slave_configure(struct scsi_device *device)
MSG_SIMPLE_TAG : 0), MSG_SIMPLE_TAG : 0),
depth_to_use); depth_to_use);
lp->s.scdev_depth = depth_to_use; lp->s.scdev_depth = depth_to_use;
sym_tune_dev_queuing(np, device->id, device->lun, reqtags); sym_tune_dev_queuing(tp, device->lun, reqtags);
if (!spi_initial_dv(device->sdev_target)) if (!spi_initial_dv(device->sdev_target))
spi_dv_device(device); spi_dv_device(device);
...@@ -1115,7 +1064,7 @@ static int sym53c8xx_slave_configure(struct scsi_device *device) ...@@ -1115,7 +1064,7 @@ static int sym53c8xx_slave_configure(struct scsi_device *device)
*/ */
static const char *sym53c8xx_info (struct Scsi_Host *host) static const char *sym53c8xx_info (struct Scsi_Host *host)
{ {
return sym_driver_name(); return SYM_DRIVER_NAME;
} }
...@@ -1178,44 +1127,47 @@ static void sym_exec_user_command (struct sym_hcb *np, struct sym_usrcmd *uc) ...@@ -1178,44 +1127,47 @@ static void sym_exec_user_command (struct sym_hcb *np, struct sym_usrcmd *uc)
case UC_SETSYNC: case UC_SETSYNC:
if (!uc->data || uc->data >= 255) { if (!uc->data || uc->data >= 255) {
tp->tinfo.goal.options = 0; tp->tgoal.iu = tp->tgoal.dt =
tp->tinfo.goal.offset = 0; tp->tgoal.qas = 0;
break; tp->tgoal.offset = 0;
} } else if (uc->data <= 9 && np->minsync_dt) {
if (uc->data <= 9 && np->minsync_dt) {
if (uc->data < np->minsync_dt) if (uc->data < np->minsync_dt)
uc->data = np->minsync_dt; uc->data = np->minsync_dt;
tp->tinfo.goal.options = PPR_OPT_MASK; tp->tgoal.iu = tp->tgoal.dt =
tp->tinfo.goal.width = 1; tp->tgoal.qas = 1;
tp->tinfo.goal.period = uc->data; tp->tgoal.width = 1;
tp->tinfo.goal.offset = np->maxoffs_dt; tp->tgoal.period = uc->data;
tp->tgoal.offset = np->maxoffs_dt;
} else { } else {
if (uc->data < np->minsync) if (uc->data < np->minsync)
uc->data = np->minsync; uc->data = np->minsync;
tp->tinfo.goal.options = 0; tp->tgoal.iu = tp->tgoal.dt =
tp->tinfo.goal.period = uc->data; tp->tgoal.qas = 0;
tp->tinfo.goal.offset = np->maxoffs; tp->tgoal.period = uc->data;
tp->tgoal.offset = np->maxoffs;
} }
tp->tgoal.check_nego = 1;
break; break;
case UC_SETWIDE: case UC_SETWIDE:
tp->tinfo.goal.width = uc->data ? 1 : 0; tp->tgoal.width = uc->data ? 1 : 0;
tp->tgoal.check_nego = 1;
break; break;
case UC_SETTAGS: case UC_SETTAGS:
for (l = 0; l < SYM_CONF_MAX_LUN; l++) for (l = 0; l < SYM_CONF_MAX_LUN; l++)
sym_tune_dev_queuing(np, t,l, uc->data); sym_tune_dev_queuing(tp, l, uc->data);
break; break;
case UC_RESETDEV: case UC_RESETDEV:
tp->to_reset = 1; tp->to_reset = 1;
np->istat_sem = SEM; np->istat_sem = SEM;
OUTB (nc_istat, SIGP|SEM); OUTB(np, nc_istat, SIGP|SEM);
break; break;
case UC_CLEARDEV: case UC_CLEARDEV:
for (l = 0; l < SYM_CONF_MAX_LUN; l++) { for (l = 0; l < SYM_CONF_MAX_LUN; l++) {
struct sym_lcb *lp = sym_lp(np, tp, l); struct sym_lcb *lp = sym_lp(tp, l);
if (lp) lp->to_clear = 1; if (lp) lp->to_clear = 1;
} }
np->istat_sem = SEM; np->istat_sem = SEM;
OUTB (nc_istat, SIGP|SEM); OUTB(np, nc_istat, SIGP|SEM);
break; break;
case UC_SETFLAG: case UC_SETFLAG:
tp->usrflags = uc->data; tp->usrflags = uc->data;
...@@ -1226,8 +1178,6 @@ static void sym_exec_user_command (struct sym_hcb *np, struct sym_usrcmd *uc) ...@@ -1226,8 +1178,6 @@ static void sym_exec_user_command (struct sym_hcb *np, struct sym_usrcmd *uc)
} }
} }
#define digit_to_bin(c) ((c) - '0')
static int skip_spaces(char *ptr, int len) static int skip_spaces(char *ptr, int len)
{ {
int cnt, c; int cnt, c;
...@@ -1239,17 +1189,10 @@ static int skip_spaces(char *ptr, int len) ...@@ -1239,17 +1189,10 @@ static int skip_spaces(char *ptr, int len)
static int get_int_arg(char *ptr, int len, u_long *pv) static int get_int_arg(char *ptr, int len, u_long *pv)
{ {
int cnt, c; char *end;
u_long v;
for (v = 0, cnt = len; cnt > 0 && (c = *ptr++) && isdigit(c); cnt--) { *pv = simple_strtoul(ptr, &end, 10);
v = (v * 10) + digit_to_bin(c); return (end - ptr);
}
if (pv)
*pv = v;
return (len - cnt);
} }
static int is_keyword(char *ptr, int len, char *verb) static int is_keyword(char *ptr, int len, char *verb)
...@@ -1260,15 +1203,14 @@ static int is_keyword(char *ptr, int len, char *verb) ...@@ -1260,15 +1203,14 @@ static int is_keyword(char *ptr, int len, char *verb)
return verb_len; return verb_len;
else else
return 0; return 0;
} }
#define SKIP_SPACES(min_spaces) \ #define SKIP_SPACES(ptr, len) \
if ((arg_len = skip_spaces(ptr, len)) < (min_spaces)) \ if ((arg_len = skip_spaces(ptr, len)) < 1) \
return -EINVAL; \ return -EINVAL; \
ptr += arg_len; len -= arg_len; ptr += arg_len; len -= arg_len;
#define GET_INT_ARG(v) \ #define GET_INT_ARG(ptr, len, v) \
if (!(arg_len = get_int_arg(ptr, len, &(v)))) \ if (!(arg_len = get_int_arg(ptr, len, &(v)))) \
return -EINVAL; \ return -EINVAL; \
ptr += arg_len; len -= arg_len; ptr += arg_len; len -= arg_len;
...@@ -1327,12 +1269,12 @@ printk("sym_user_command: arg_len=%d, cmd=%ld\n", arg_len, uc->cmd); ...@@ -1327,12 +1269,12 @@ printk("sym_user_command: arg_len=%d, cmd=%ld\n", arg_len, uc->cmd);
case UC_SETFLAG: case UC_SETFLAG:
case UC_RESETDEV: case UC_RESETDEV:
case UC_CLEARDEV: case UC_CLEARDEV:
SKIP_SPACES(1); SKIP_SPACES(ptr, len);
if ((arg_len = is_keyword(ptr, len, "all")) != 0) { if ((arg_len = is_keyword(ptr, len, "all")) != 0) {
ptr += arg_len; len -= arg_len; ptr += arg_len; len -= arg_len;
uc->target = ~0; uc->target = ~0;
} else { } else {
GET_INT_ARG(target); GET_INT_ARG(ptr, len, target);
uc->target = (1<<target); uc->target = (1<<target);
#ifdef DEBUG_PROC_INFO #ifdef DEBUG_PROC_INFO
printk("sym_user_command: target=%ld\n", target); printk("sym_user_command: target=%ld\n", target);
...@@ -1346,8 +1288,8 @@ printk("sym_user_command: target=%ld\n", target); ...@@ -1346,8 +1288,8 @@ printk("sym_user_command: target=%ld\n", target);
case UC_SETSYNC: case UC_SETSYNC:
case UC_SETTAGS: case UC_SETTAGS:
case UC_SETWIDE: case UC_SETWIDE:
SKIP_SPACES(1); SKIP_SPACES(ptr, len);
GET_INT_ARG(uc->data); GET_INT_ARG(ptr, len, uc->data);
#ifdef DEBUG_PROC_INFO #ifdef DEBUG_PROC_INFO
printk("sym_user_command: data=%ld\n", uc->data); printk("sym_user_command: data=%ld\n", uc->data);
#endif #endif
...@@ -1355,7 +1297,7 @@ printk("sym_user_command: data=%ld\n", uc->data); ...@@ -1355,7 +1297,7 @@ printk("sym_user_command: data=%ld\n", uc->data);
#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT #ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
case UC_SETDEBUG: case UC_SETDEBUG:
while (len > 0) { while (len > 0) {
SKIP_SPACES(1); SKIP_SPACES(ptr, len);
if ((arg_len = is_keyword(ptr, len, "alloc"))) if ((arg_len = is_keyword(ptr, len, "alloc")))
uc->data |= DEBUG_ALLOC; uc->data |= DEBUG_ALLOC;
else if ((arg_len = is_keyword(ptr, len, "phase"))) else if ((arg_len = is_keyword(ptr, len, "phase")))
...@@ -1389,7 +1331,7 @@ printk("sym_user_command: data=%ld\n", uc->data); ...@@ -1389,7 +1331,7 @@ printk("sym_user_command: data=%ld\n", uc->data);
#endif /* SYM_LINUX_DEBUG_CONTROL_SUPPORT */ #endif /* SYM_LINUX_DEBUG_CONTROL_SUPPORT */
case UC_SETFLAG: case UC_SETFLAG:
while (len > 0) { while (len > 0) {
SKIP_SPACES(1); SKIP_SPACES(ptr, len);
if ((arg_len = is_keyword(ptr, len, "no_disc"))) if ((arg_len = is_keyword(ptr, len, "no_disc")))
uc->data &= ~SYM_DISC_ENABLED; uc->data &= ~SYM_DISC_ENABLED;
else else
...@@ -1499,15 +1441,9 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len) ...@@ -1499,15 +1441,9 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer, static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer,
char **start, off_t offset, int length, int func) char **start, off_t offset, int length, int func)
{ {
struct host_data *host_data; struct sym_hcb *np = sym_get_hcb(host);
struct sym_hcb *np = NULL;
int retv; int retv;
host_data = (struct host_data *) host->hostdata;
np = host_data->ncb;
if (!np)
return -EINVAL;
if (func) { if (func) {
#ifdef SYM_LINUX_USER_COMMAND_SUPPORT #ifdef SYM_LINUX_USER_COMMAND_SUPPORT
retv = sym_user_command(np, buffer, length); retv = sym_user_command(np, buffer, length);
...@@ -1531,19 +1467,17 @@ static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer, ...@@ -1531,19 +1467,17 @@ static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer,
/* /*
* Free controller resources. * Free controller resources.
*/ */
static void sym_free_resources(struct sym_hcb *np) static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev)
{ {
/* /*
* Free O/S specific resources. * Free O/S specific resources.
*/ */
if (np->s.irq) if (np->s.irq)
free_irq(np->s.irq, np); free_irq(np->s.irq, np);
#ifndef SYM_CONF_IOMAPPED if (np->s.ioaddr)
if (np->s.mmio_va) pci_iounmap(pdev, np->s.ioaddr);
iounmap(np->s.mmio_va); if (np->s.ramaddr)
#endif pci_iounmap(pdev, np->s.ramaddr);
if (np->s.ram_va)
iounmap(np->s.ram_va);
/* /*
* Free O/S independent resources. * Free O/S independent resources.
*/ */
...@@ -1592,13 +1526,14 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, ...@@ -1592,13 +1526,14 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
struct host_data *host_data; struct host_data *host_data;
struct sym_hcb *np = NULL; struct sym_hcb *np = NULL;
struct Scsi_Host *instance = NULL; struct Scsi_Host *instance = NULL;
struct pci_dev *pdev = dev->pdev;
unsigned long flags; unsigned long flags;
struct sym_fw *fw; struct sym_fw *fw;
printk(KERN_INFO printk(KERN_INFO
"sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n", "sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n",
unit, dev->chip.name, dev->chip.revision_id, unit, dev->chip.name, dev->chip.revision_id,
pci_name(dev->pdev), IRQ_PRM(dev->s.irq)); pci_name(pdev), IRQ_PRM(pdev->irq));
/* /*
* Get the firmware for this chip. * Get the firmware for this chip.
...@@ -1621,22 +1556,22 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, ...@@ -1621,22 +1556,22 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
* We keep track in the HCB of all the resources that * We keep track in the HCB of all the resources that
* are to be released on error. * are to be released on error.
*/ */
np = __sym_calloc_dma(dev->pdev, sizeof(*np), "HCB"); np = __sym_calloc_dma(&pdev->dev, sizeof(*np), "HCB");
if (!np) if (!np)
goto attach_failed; goto attach_failed;
np->s.device = dev->pdev; np->s.device = pdev;
np->bus_dmat = dev->pdev; /* Result in 1 DMA pool per HBA */ np->bus_dmat = &pdev->dev; /* Result in 1 DMA pool per HBA */
host_data->ncb = np; host_data->ncb = np;
np->s.host = instance; np->s.host = instance;
pci_set_drvdata(dev->pdev, np); pci_set_drvdata(pdev, np);
/* /*
* Copy some useful infos to the HCB. * Copy some useful infos to the HCB.
*/ */
np->hcb_ba = vtobus(np); np->hcb_ba = vtobus(np);
np->verbose = sym_driver_setup.verbose; np->verbose = sym_driver_setup.verbose;
np->s.device = dev->pdev; np->s.device = pdev;
np->s.unit = unit; np->s.unit = unit;
np->device_id = dev->chip.device_id; np->device_id = dev->chip.device_id;
np->revision_id = dev->chip.revision_id; np->revision_id = dev->chip.revision_id;
...@@ -1659,58 +1594,35 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, ...@@ -1659,58 +1594,35 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
* Try to map the controller chip to * Try to map the controller chip to
* virtual and physical memory. * virtual and physical memory.
*/ */
np->mmio_ba = (u32)dev->s.base; np->mmio_ba = (u32)dev->mmio_base;
np->s.io_ws = (np->features & FE_IO256)? 256 : 128; np->s.ioaddr = dev->s.ioaddr;
np->s.ramaddr = dev->s.ramaddr;
#ifndef SYM_CONF_IOMAPPED np->s.io_ws = (np->features & FE_IO256) ? 256 : 128;
np->s.mmio_va = ioremap(dev->s.base_c, np->s.io_ws);
if (!np->s.mmio_va) {
printf_err("%s: can't map PCI MMIO region\n", sym_name(np));
goto attach_failed;
} else if (sym_verbose > 1)
printf_info("%s: using memory mapped IO\n", sym_name(np));
#endif /* !defined SYM_CONF_IOMAPPED */
np->s.io_port = dev->s.io_port;
/* /*
* Map on-chip RAM if present and supported. * Map on-chip RAM if present and supported.
*/ */
if (!(np->features & FE_RAM)) if (!(np->features & FE_RAM))
dev->s.base_2 = 0; dev->ram_base = 0;
if (dev->s.base_2) { if (dev->ram_base) {
np->ram_ba = (u32)dev->s.base_2; np->ram_ba = (u32)dev->ram_base;
if (np->features & FE_RAM8K) np->ram_ws = (np->features & FE_RAM8K) ? 8192 : 4096;
np->ram_ws = 8192;
else
np->ram_ws = 4096;
np->s.ram_va = ioremap(dev->s.base_2_c, np->ram_ws);
if (!np->s.ram_va) {
printf_err("%s: can't map PCI MEMORY region\n",
sym_name(np));
goto attach_failed;
}
} }
/* if (sym_hcb_attach(instance, fw, dev->nvram))
* Perform O/S independent stuff.
*/
if (sym_hcb_attach(np, fw, dev->nvram))
goto attach_failed; goto attach_failed;
/* /*
* Install the interrupt handler. * Install the interrupt handler.
* If we synchonize the C code with SCRIPTS on interrupt, * If we synchonize the C code with SCRIPTS on interrupt,
* we donnot want to share the INTR line at all. * we do not want to share the INTR line at all.
*/ */
if (request_irq(dev->s.irq, sym53c8xx_intr, SA_SHIRQ, if (request_irq(pdev->irq, sym53c8xx_intr, SA_SHIRQ, NAME53C8XX, np)) {
NAME53C8XX, np)) {
printf_err("%s: request irq %d failure\n", printf_err("%s: request irq %d failure\n",
sym_name(np), dev->s.irq); sym_name(np), pdev->irq);
goto attach_failed; goto attach_failed;
} }
np->s.irq = dev->s.irq; np->s.irq = pdev->irq;
/* /*
* After SCSI devices have been opened, we cannot * After SCSI devices have been opened, we cannot
...@@ -1742,14 +1654,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, ...@@ -1742,14 +1654,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
instance->this_id = np->myaddr; instance->this_id = np->myaddr;
instance->max_id = np->maxwide ? 16 : 8; instance->max_id = np->maxwide ? 16 : 8;
instance->max_lun = SYM_CONF_MAX_LUN; instance->max_lun = SYM_CONF_MAX_LUN;
#ifndef SYM_CONF_IOMAPPED instance->unique_id = pci_resource_start(pdev, 0);
instance->base = (unsigned long) np->s.mmio_va;
#endif
instance->irq = np->s.irq;
instance->unique_id = np->s.io_port;
instance->io_port = np->s.io_port;
instance->n_io_port = np->s.io_ws;
instance->dma_channel = 0;
instance->cmd_per_lun = SYM_CONF_MAX_TAG; instance->cmd_per_lun = SYM_CONF_MAX_TAG;
instance->can_queue = (SYM_CONF_MAX_START-2); instance->can_queue = (SYM_CONF_MAX_START-2);
instance->sg_tablesize = SYM_CONF_MAX_SG; instance->sg_tablesize = SYM_CONF_MAX_SG;
...@@ -1770,7 +1675,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt, ...@@ -1770,7 +1675,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
return NULL; return NULL;
printf_info("%s: giving up ...\n", sym_name(np)); printf_info("%s: giving up ...\n", sym_name(np));
if (np) if (np)
sym_free_resources(np); sym_free_resources(np, pdev);
scsi_host_put(instance); scsi_host_put(instance);
return NULL; return NULL;
...@@ -1787,23 +1692,7 @@ static void __devinit sym_get_nvram(struct sym_device *devp, struct sym_nvram *n ...@@ -1787,23 +1692,7 @@ static void __devinit sym_get_nvram(struct sym_device *devp, struct sym_nvram *n
devp->device_id = devp->chip.device_id; devp->device_id = devp->chip.device_id;
nvp->type = 0; nvp->type = 0;
/*
* Get access to chip IO registers
*/
#ifndef SYM_CONF_IOMAPPED
devp->s.mmio_va = ioremap(devp->s.base_c, 128);
if (!devp->s.mmio_va)
return;
#endif
sym_read_nvram(devp, nvp); sym_read_nvram(devp, nvp);
/*
* Release access to chip IO registers
*/
#ifndef SYM_CONF_IOMAPPED
iounmap(devp->s.mmio_va);
#endif
} }
#else #else
static inline void sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp) static inline void sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp)
...@@ -1813,15 +1702,15 @@ static inline void sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp) ...@@ -1813,15 +1702,15 @@ static inline void sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp)
static int __devinit sym_check_supported(struct sym_device *device) static int __devinit sym_check_supported(struct sym_device *device)
{ {
struct sym_pci_chip *chip; struct sym_chip *chip;
struct pci_dev *pdev = device->pdev; struct pci_dev *pdev = device->pdev;
u_char revision; u_char revision;
unsigned long io_port = device->s.io_port; unsigned long io_port = pci_resource_start(pdev, 0);
unsigned long base = device->s.base;
int i; int i;
/* /*
* If user excluded this chip, do not initialize it. * If user excluded this chip, do not initialize it.
* I hate this code so much. Must kill it.
*/ */
if (io_port) { if (io_port) {
for (i = 0 ; i < 8 ; i++) { for (i = 0 ; i < 8 ; i++) {
...@@ -1830,33 +1719,15 @@ static int __devinit sym_check_supported(struct sym_device *device) ...@@ -1830,33 +1719,15 @@ static int __devinit sym_check_supported(struct sym_device *device)
} }
} }
/*
* Check if the chip has been assigned resources we need.
* XXX: can this still happen with Linux 2.6's PCI layer?
*/
#ifdef SYM_CONF_IOMAPPED
if (!io_port) {
printf_info("%s: IO base address disabled.\n",
sym_name(device));
return -ENODEV;
}
#else
if (!base) {
printf_info("%s: MMIO base address disabled.\n",
sym_name(device));
return -ENODEV;
}
#endif
/* /*
* Check if the chip is supported. Then copy the chip description * Check if the chip is supported. Then copy the chip description
* to our device structure so we can make it match the actual device * to our device structure so we can make it match the actual device
* and options. * and options.
*/ */
pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);
chip = sym_lookup_pci_chip_table(pdev->device, revision); chip = sym_lookup_chip_table(pdev->device, revision);
if (!chip) { if (!chip) {
printf_info("%s: device not supported\n", sym_name(device)); dev_info(&pdev->dev, "device not supported\n");
return -ENODEV; return -ENODEV;
} }
memcpy(&device->chip, chip, sizeof(device->chip)); memcpy(&device->chip, chip, sizeof(device->chip));
...@@ -1871,11 +1742,9 @@ static int __devinit sym_check_supported(struct sym_device *device) ...@@ -1871,11 +1742,9 @@ static int __devinit sym_check_supported(struct sym_device *device)
*/ */
static int __devinit sym_check_raid(struct sym_device *device) static int __devinit sym_check_raid(struct sym_device *device)
{ {
unsigned long base_2_c = device->s.base_2_c;
unsigned int ram_size, ram_val; unsigned int ram_size, ram_val;
void __iomem *ram_ptr;
if (!base_2_c) if (!device->s.ramaddr)
return 0; return 0;
if (device->chip.features & FE_RAM8K) if (device->chip.features & FE_RAM8K)
...@@ -1883,23 +1752,18 @@ static int __devinit sym_check_raid(struct sym_device *device) ...@@ -1883,23 +1752,18 @@ static int __devinit sym_check_raid(struct sym_device *device)
else else
ram_size = 4096; ram_size = 4096;
ram_ptr = ioremap(base_2_c, ram_size); ram_val = readl(device->s.ramaddr + ram_size - 16);
if (!ram_ptr)
return 0;
ram_val = readl(ram_ptr + ram_size - 16);
iounmap(ram_ptr);
if (ram_val != 0x52414944) if (ram_val != 0x52414944)
return 0; return 0;
printf_info("%s: not initializing, driven by RAID controller.\n", dev_info(&device->pdev->dev,
sym_name(device)); "not initializing, driven by RAID controller.\n");
return -ENODEV; return -ENODEV;
} }
static int __devinit sym_set_workarounds(struct sym_device *device) static int __devinit sym_set_workarounds(struct sym_device *device)
{ {
struct sym_pci_chip *chip = &device->chip; struct sym_chip *chip = &device->chip;
struct pci_dev *pdev = device->pdev; struct pci_dev *pdev = device->pdev;
u_short status_reg; u_short status_reg;
...@@ -1952,26 +1816,25 @@ static int __devinit sym_set_workarounds(struct sym_device *device) ...@@ -1952,26 +1816,25 @@ static int __devinit sym_set_workarounds(struct sym_device *device)
static void __devinit static void __devinit
sym_init_device(struct pci_dev *pdev, struct sym_device *device) sym_init_device(struct pci_dev *pdev, struct sym_device *device)
{ {
unsigned long base, base_2;
int i; int i;
device->host_id = SYM_SETUP_HOST_ID; device->host_id = SYM_SETUP_HOST_ID;
device->pdev = pdev; device->pdev = pdev;
device->s.irq = pdev->irq;
/* Choose some short name for this device */
sprintf(device->s.inst_name, "sym.%d.%d.%d", pdev->bus->number,
PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
device->s.io_port = pdev->resource[0].start; i = pci_get_base_address(pdev, 1, &device->mmio_base);
pci_get_base_address(pdev, i, &device->ram_base);
device->s.base_c = pdev->resource[1].start; #ifndef CONFIG_SCSI_SYM53C8XX_IOMAPPED
i = pci_get_base_address(pdev, 1, &base); if (device->mmio_base)
device->s.base = base & PCI_BASE_ADDRESS_MEM_MASK; device->s.ioaddr = pci_iomap(pdev, 1,
pci_resource_len(pdev, 1));
device->s.base_2_c = pdev->resource[i].start; #endif
pci_get_base_address(pdev, i, &base_2); if (!device->s.ioaddr)
device->s.base_2 = base_2 & PCI_BASE_ADDRESS_MEM_MASK; device->s.ioaddr = pci_iomap(pdev, 0,
pci_resource_len(pdev, 0));
if (device->ram_base)
device->s.ramaddr = pci_iomap(pdev, i,
pci_resource_len(pdev, i));
} }
/* /*
...@@ -2027,7 +1890,7 @@ static void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev) ...@@ -2027,7 +1890,7 @@ static void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
* Detach the host. * Detach the host.
* We have to free resources and halt the NCR chip. * We have to free resources and halt the NCR chip.
*/ */
static int sym_detach(struct sym_hcb *np) static int sym_detach(struct sym_hcb *np, struct pci_dev *pdev)
{ {
printk("%s: detaching ...\n", sym_name(np)); printk("%s: detaching ...\n", sym_name(np));
...@@ -2039,11 +1902,11 @@ static int sym_detach(struct sym_hcb *np) ...@@ -2039,11 +1902,11 @@ static int sym_detach(struct sym_hcb *np)
* so, since we may not be safe if interrupts occur. * so, since we may not be safe if interrupts occur.
*/ */
printk("%s: resetting chip\n", sym_name(np)); printk("%s: resetting chip\n", sym_name(np));
OUTB (nc_istat, SRST); OUTB(np, nc_istat, SRST);
UDELAY (10); udelay(10);
OUTB (nc_istat, 0); OUTB(np, nc_istat, 0);
sym_free_resources(np); sym_free_resources(np, pdev);
return 1; return 1;
} }
...@@ -2056,7 +1919,9 @@ static struct scsi_host_template sym2_template = { ...@@ -2056,7 +1919,9 @@ static struct scsi_host_template sym2_template = {
.name = "sym53c8xx", .name = "sym53c8xx",
.info = sym53c8xx_info, .info = sym53c8xx_info,
.queuecommand = sym53c8xx_queue_command, .queuecommand = sym53c8xx_queue_command,
.slave_alloc = sym53c8xx_slave_alloc,
.slave_configure = sym53c8xx_slave_configure, .slave_configure = sym53c8xx_slave_configure,
.slave_destroy = sym53c8xx_slave_destroy,
.eh_abort_handler = sym53c8xx_eh_abort_handler, .eh_abort_handler = sym53c8xx_eh_abort_handler,
.eh_device_reset_handler = sym53c8xx_eh_device_reset_handler, .eh_device_reset_handler = sym53c8xx_eh_device_reset_handler,
.eh_bus_reset_handler = sym53c8xx_eh_bus_reset_handler, .eh_bus_reset_handler = sym53c8xx_eh_bus_reset_handler,
...@@ -2116,7 +1981,7 @@ static int __devinit sym2_probe(struct pci_dev *pdev, ...@@ -2116,7 +1981,7 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
return 0; return 0;
detach: detach:
sym_detach(pci_get_drvdata(pdev)); sym_detach(pci_get_drvdata(pdev), pdev);
free: free:
pci_release_regions(pdev); pci_release_regions(pdev);
disable: disable:
...@@ -2133,7 +1998,7 @@ static void __devexit sym2_remove(struct pci_dev *pdev) ...@@ -2133,7 +1998,7 @@ static void __devexit sym2_remove(struct pci_dev *pdev)
scsi_remove_host(host); scsi_remove_host(host);
scsi_host_put(host); scsi_host_put(host);
sym_detach(np); sym_detach(np, pdev);
pci_release_regions(pdev); pci_release_regions(pdev);
pci_disable_device(pdev); pci_disable_device(pdev);
...@@ -2143,12 +2008,12 @@ static void __devexit sym2_remove(struct pci_dev *pdev) ...@@ -2143,12 +2008,12 @@ static void __devexit sym2_remove(struct pci_dev *pdev)
static void sym2_get_signalling(struct Scsi_Host *shost) static void sym2_get_signalling(struct Scsi_Host *shost)
{ {
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; struct sym_hcb *np = sym_get_hcb(shost);
enum spi_signal_type type; enum spi_signal_type type;
switch (np->scsi_mode) { switch (np->scsi_mode) {
case SMODE_SE: case SMODE_SE:
type = SPI_SIGNAL_SE; type = SPI_SIGNAL_SE;
break; break;
case SMODE_LVD: case SMODE_LVD:
type = SPI_SIGNAL_LVD; type = SPI_SIGNAL_LVD;
...@@ -2163,152 +2028,97 @@ static void sym2_get_signalling(struct Scsi_Host *shost) ...@@ -2163,152 +2028,97 @@ static void sym2_get_signalling(struct Scsi_Host *shost)
spi_signalling(shost) = type; spi_signalling(shost) = type;
} }
static void sym2_get_offset(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
struct sym_tcb *tp = &np->target[starget->id];
spi_offset(starget) = tp->tinfo.curr.offset;
}
static void sym2_set_offset(struct scsi_target *starget, int offset) static void sym2_set_offset(struct scsi_target *starget, int offset)
{ {
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; struct sym_hcb *np = sym_get_hcb(shost);
struct sym_tcb *tp = &np->target[starget->id];
tp->tinfo.goal.offset = offset;
}
static void sym2_get_period(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
struct sym_tcb *tp = &np->target[starget->id]; struct sym_tcb *tp = &np->target[starget->id];
spi_period(starget) = tp->tinfo.curr.period; tp->tgoal.offset = offset;
tp->tgoal.check_nego = 1;
} }
static void sym2_set_period(struct scsi_target *starget, int period) static void sym2_set_period(struct scsi_target *starget, int period)
{ {
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; struct sym_hcb *np = sym_get_hcb(shost);
struct sym_tcb *tp = &np->target[starget->id]; struct sym_tcb *tp = &np->target[starget->id];
/* have to have DT for these transfers */ /* have to have DT for these transfers */
if (period <= np->minsync) if (period <= np->minsync)
tp->tinfo.goal.options |= PPR_OPT_DT; tp->tgoal.dt = 1;
tp->tinfo.goal.period = period; tp->tgoal.period = period;
} tp->tgoal.check_nego = 1;
static void sym2_get_width(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
struct sym_tcb *tp = &np->target[starget->id];
spi_width(starget) = tp->tinfo.curr.width ? 1 : 0;
} }
static void sym2_set_width(struct scsi_target *starget, int width) static void sym2_set_width(struct scsi_target *starget, int width)
{ {
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; struct sym_hcb *np = sym_get_hcb(shost);
struct sym_tcb *tp = &np->target[starget->id]; struct sym_tcb *tp = &np->target[starget->id];
/* It is illegal to have DT set on narrow transfers. If DT is /* It is illegal to have DT set on narrow transfers. If DT is
* clear, we must also clear IU and QAS. */ * clear, we must also clear IU and QAS. */
if (width == 0) if (width == 0)
tp->tinfo.goal.options &= ~PPR_OPT_MASK; tp->tgoal.iu = tp->tgoal.dt = tp->tgoal.qas = 0;
tp->tinfo.goal.width = width; tp->tgoal.width = width;
} tp->tgoal.check_nego = 1;
static void sym2_get_dt(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
struct sym_tcb *tp = &np->target[starget->id];
spi_dt(starget) = (tp->tinfo.curr.options & PPR_OPT_DT) ? 1 : 0;
} }
static void sym2_set_dt(struct scsi_target *starget, int dt) static void sym2_set_dt(struct scsi_target *starget, int dt)
{ {
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; struct sym_hcb *np = sym_get_hcb(shost);
struct sym_tcb *tp = &np->target[starget->id]; struct sym_tcb *tp = &np->target[starget->id];
/* We must clear QAS and IU if DT is clear */ /* We must clear QAS and IU if DT is clear */
if (dt) if (dt)
tp->tinfo.goal.options |= PPR_OPT_DT; tp->tgoal.dt = 1;
else else
tp->tinfo.goal.options &= ~PPR_OPT_MASK; tp->tgoal.iu = tp->tgoal.dt = tp->tgoal.qas = 0;
} tp->tgoal.check_nego = 1;
static void sym2_get_iu(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
struct sym_tcb *tp = &np->target[starget->id];
spi_iu(starget) = (tp->tinfo.curr.options & PPR_OPT_IU) ? 1 : 0;
} }
static void sym2_set_iu(struct scsi_target *starget, int iu) static void sym2_set_iu(struct scsi_target *starget, int iu)
{ {
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; struct sym_hcb *np = sym_get_hcb(shost);
struct sym_tcb *tp = &np->target[starget->id]; struct sym_tcb *tp = &np->target[starget->id];
if (iu) if (iu)
tp->tinfo.goal.options |= PPR_OPT_IU | PPR_OPT_DT; tp->tgoal.iu = tp->tgoal.dt = 1;
else else
tp->tinfo.goal.options &= ~PPR_OPT_IU; tp->tgoal.iu = 0;
} tp->tgoal.check_nego = 1;
static void sym2_get_qas(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
struct sym_tcb *tp = &np->target[starget->id];
spi_qas(starget) = (tp->tinfo.curr.options & PPR_OPT_QAS) ? 1 : 0;
} }
static void sym2_set_qas(struct scsi_target *starget, int qas) static void sym2_set_qas(struct scsi_target *starget, int qas)
{ {
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb; struct sym_hcb *np = sym_get_hcb(shost);
struct sym_tcb *tp = &np->target[starget->id]; struct sym_tcb *tp = &np->target[starget->id];
if (qas) if (qas)
tp->tinfo.goal.options |= PPR_OPT_QAS | PPR_OPT_DT; tp->tgoal.dt = tp->tgoal.qas = 1;
else else
tp->tinfo.goal.options &= ~PPR_OPT_QAS; tp->tgoal.qas = 0;
tp->tgoal.check_nego = 1;
} }
static struct spi_function_template sym2_transport_functions = { static struct spi_function_template sym2_transport_functions = {
.set_offset = sym2_set_offset, .set_offset = sym2_set_offset,
.get_offset = sym2_get_offset,
.show_offset = 1, .show_offset = 1,
.set_period = sym2_set_period, .set_period = sym2_set_period,
.get_period = sym2_get_period,
.show_period = 1, .show_period = 1,
.set_width = sym2_set_width, .set_width = sym2_set_width,
.get_width = sym2_get_width,
.show_width = 1, .show_width = 1,
.get_dt = sym2_get_dt,
.set_dt = sym2_set_dt, .set_dt = sym2_set_dt,
.show_dt = 1, .show_dt = 1,
.get_iu = sym2_get_iu,
.set_iu = sym2_set_iu, .set_iu = sym2_set_iu,
.show_iu = 1, .show_iu = 1,
.get_qas = sym2_get_qas,
.set_qas = sym2_set_qas, .set_qas = sym2_set_qas,
.show_qas = 1, .show_qas = 1,
.get_signalling = sym2_get_signalling, .get_signalling = sym2_get_signalling,
...@@ -2370,7 +2180,7 @@ static int __init sym2_init(void) ...@@ -2370,7 +2180,7 @@ static int __init sym2_init(void)
if (!sym2_transport_template) if (!sym2_transport_template)
return -ENODEV; return -ENODEV;
error = pci_module_init(&sym2_driver); error = pci_register_driver(&sym2_driver);
if (error) if (error)
spi_release_transport(sym2_transport_template); spi_release_transport(sym2_transport_template);
return error; return error;
......
...@@ -56,9 +56,10 @@ ...@@ -56,9 +56,10 @@
#include <scsi/scsi.h> #include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h> #include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h> #include <scsi/scsi_device.h>
#include <scsi/scsi_transport_spi.h>
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
#include "sym_conf.h" #include "sym53c8xx.h"
#include "sym_defs.h" #include "sym_defs.h"
#include "sym_misc.h" #include "sym_misc.h"
...@@ -70,7 +71,6 @@ ...@@ -70,7 +71,6 @@
#define SYM_OPT_HANDLE_DIR_UNKNOWN #define SYM_OPT_HANDLE_DIR_UNKNOWN
#define SYM_OPT_HANDLE_DEVICE_QUEUEING #define SYM_OPT_HANDLE_DEVICE_QUEUEING
#define SYM_OPT_LIMIT_COMMAND_REORDERING #define SYM_OPT_LIMIT_COMMAND_REORDERING
#define SYM_OPT_ANNOUNCE_TRANSFER_RATE
/* /*
* Print a message with severity. * Print a message with severity.
...@@ -85,11 +85,6 @@ ...@@ -85,11 +85,6 @@
#define printf_debug(args...) printk(KERN_DEBUG args) #define printf_debug(args...) printk(KERN_DEBUG args)
#define printf(args...) printk(args) #define printf(args...) printk(args)
/*
* Insert a delay in micro-seconds
*/
#define sym_udelay(us) udelay(us)
/* /*
* A 'read barrier' flushes any data that have been prefetched * A 'read barrier' flushes any data that have been prefetched
* by the processor due to out of order execution. Such a barrier * by the processor due to out of order execution. Such a barrier
...@@ -110,13 +105,6 @@ ...@@ -110,13 +105,6 @@
#define MEMORY_READ_BARRIER() rmb() #define MEMORY_READ_BARRIER() rmb()
#define MEMORY_WRITE_BARRIER() wmb() #define MEMORY_WRITE_BARRIER() wmb()
/*
* Let the compiler know about driver data structure names.
*/
typedef struct sym_tcb *tcb_p;
typedef struct sym_lcb *lcb_p;
typedef struct sym_ccb *ccb_p;
/* /*
* IO functions definition for big/little endian CPU support. * IO functions definition for big/little endian CPU support.
* For now, PCI chips are only supported in little endian addressing mode, * For now, PCI chips are only supported in little endian addressing mode,
...@@ -124,10 +112,6 @@ typedef struct sym_ccb *ccb_p; ...@@ -124,10 +112,6 @@ typedef struct sym_ccb *ccb_p;
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
#define inw_l2b inw
#define inl_l2b inl
#define outw_b2l outw
#define outl_b2l outl
#define readw_l2b readw #define readw_l2b readw
#define readl_l2b readl #define readl_l2b readl
#define writew_b2l writew #define writew_b2l writew
...@@ -135,11 +119,6 @@ typedef struct sym_ccb *ccb_p; ...@@ -135,11 +119,6 @@ typedef struct sym_ccb *ccb_p;
#else /* little endian */ #else /* little endian */
#define inw_raw inw
#define inl_raw inl
#define outw_raw outw
#define outl_raw outl
#define readw_raw readw #define readw_raw readw
#define readl_raw readl #define readl_raw readl
#define writew_raw writew #define writew_raw writew
...@@ -151,27 +130,6 @@ typedef struct sym_ccb *ccb_p; ...@@ -151,27 +130,6 @@ typedef struct sym_ccb *ccb_p;
#error "Chips in BIG ENDIAN addressing mode are not (yet) supported" #error "Chips in BIG ENDIAN addressing mode are not (yet) supported"
#endif #endif
/*
* If the chip uses big endian addressing mode over the
* PCI, actual io register addresses for byte and word
* accesses must be changed according to lane routing.
* Btw, sym_offb() and sym_offw() macros only apply to
* constants and so donnot generate bloated code.
*/
#if defined(SYM_CONF_CHIP_BIG_ENDIAN)
#define sym_offb(o) (((o)&~3)+((~((o)&3))&3))
#define sym_offw(o) (((o)&~3)+((~((o)&3))&2))
#else
#define sym_offb(o) (o)
#define sym_offw(o) (o)
#endif
/* /*
* If the CPU and the chip use same endian-ness addressing, * If the CPU and the chip use same endian-ness addressing,
* no byte reordering is needed for script patching. * no byte reordering is needed for script patching.
...@@ -180,117 +138,9 @@ typedef struct sym_ccb *ccb_p; ...@@ -180,117 +138,9 @@ typedef struct sym_ccb *ccb_p;
* from the script. * from the script.
*/ */
#if defined(__BIG_ENDIAN) && !defined(SYM_CONF_CHIP_BIG_ENDIAN)
#define cpu_to_scr(dw) cpu_to_le32(dw) #define cpu_to_scr(dw) cpu_to_le32(dw)
#define scr_to_cpu(dw) le32_to_cpu(dw) #define scr_to_cpu(dw) le32_to_cpu(dw)
#elif defined(__LITTLE_ENDIAN) && defined(SYM_CONF_CHIP_BIG_ENDIAN)
#define cpu_to_scr(dw) cpu_to_be32(dw)
#define scr_to_cpu(dw) be32_to_cpu(dw)
#else
#define cpu_to_scr(dw) (dw)
#define scr_to_cpu(dw) (dw)
#endif
/*
* Access to the controller chip.
*
* If SYM_CONF_IOMAPPED is defined, the driver will use
* normal IOs instead of the MEMORY MAPPED IO method
* recommended by PCI specifications.
* If all PCI bridges, host brigdes and architectures
* would have been correctly designed for PCI, this
* option would be useless.
*
* If the CPU and the chip use same endian-ness addressing,
* no byte reordering is needed for accessing chip io
* registers. Functions suffixed by '_raw' are assumed
* to access the chip over the PCI without doing byte
* reordering. Functions suffixed by '_l2b' are
* assumed to perform little-endian to big-endian byte
* reordering, those suffixed by '_b2l' blah, blah,
* blah, ...
*/
#if defined(SYM_CONF_IOMAPPED)
/*
* IO mapped only input / ouput
*/
#define INB_OFF(o) inb (np->s.io_port + sym_offb(o))
#define OUTB_OFF(o, val) outb ((val), np->s.io_port + sym_offb(o))
#if defined(__BIG_ENDIAN) && !defined(SYM_CONF_CHIP_BIG_ENDIAN)
#define INW_OFF(o) inw_l2b (np->s.io_port + sym_offw(o))
#define INL_OFF(o) inl_l2b (np->s.io_port + (o))
#define OUTW_OFF(o, val) outw_b2l ((val), np->s.io_port + sym_offw(o))
#define OUTL_OFF(o, val) outl_b2l ((val), np->s.io_port + (o))
#elif defined(__LITTLE_ENDIAN) && defined(SYM_CONF_CHIP_BIG_ENDIAN)
#define INW_OFF(o) inw_b2l (np->s.io_port + sym_offw(o))
#define INL_OFF(o) inl_b2l (np->s.io_port + (o))
#define OUTW_OFF(o, val) outw_l2b ((val), np->s.io_port + sym_offw(o))
#define OUTL_OFF(o, val) outl_l2b ((val), np->s.io_port + (o))
#else
#define INW_OFF(o) inw_raw (np->s.io_port + sym_offw(o))
#define INL_OFF(o) inl_raw (np->s.io_port + (o))
#define OUTW_OFF(o, val) outw_raw ((val), np->s.io_port + sym_offw(o))
#define OUTL_OFF(o, val) outl_raw ((val), np->s.io_port + (o))
#endif /* ENDIANs */
#else /* defined SYM_CONF_IOMAPPED */
/*
* MEMORY mapped IO input / output
*/
#define INB_OFF(o) readb(np->s.mmio_va + sym_offb(o))
#define OUTB_OFF(o, val) writeb((val), np->s.mmio_va + sym_offb(o))
#if defined(__BIG_ENDIAN) && !defined(SYM_CONF_CHIP_BIG_ENDIAN)
#define INW_OFF(o) readw_l2b(np->s.mmio_va + sym_offw(o))
#define INL_OFF(o) readl_l2b(np->s.mmio_va + (o))
#define OUTW_OFF(o, val) writew_b2l((val), np->s.mmio_va + sym_offw(o))
#define OUTL_OFF(o, val) writel_b2l((val), np->s.mmio_va + (o))
#elif defined(__LITTLE_ENDIAN) && defined(SYM_CONF_CHIP_BIG_ENDIAN)
#define INW_OFF(o) readw_b2l(np->s.mmio_va + sym_offw(o))
#define INL_OFF(o) readl_b2l(np->s.mmio_va + (o))
#define OUTW_OFF(o, val) writew_l2b((val), np->s.mmio_va + sym_offw(o))
#define OUTL_OFF(o, val) writel_l2b((val), np->s.mmio_va + (o))
#else
#define INW_OFF(o) readw_raw(np->s.mmio_va + sym_offw(o))
#define INL_OFF(o) readl_raw(np->s.mmio_va + (o))
#define OUTW_OFF(o, val) writew_raw((val), np->s.mmio_va + sym_offw(o))
#define OUTL_OFF(o, val) writel_raw((val), np->s.mmio_va + (o))
#endif
#endif /* defined SYM_CONF_IOMAPPED */
#define OUTRAM_OFF(o, a, l) memcpy_toio(np->s.ram_va + (o), (a), (l))
/* /*
* Remap some status field values. * Remap some status field values.
*/ */
...@@ -360,9 +210,8 @@ struct sym_shcb { ...@@ -360,9 +210,8 @@ struct sym_shcb {
struct Scsi_Host *host; struct Scsi_Host *host;
void __iomem * mmio_va; /* MMIO kernel virtual address */ void __iomem * ioaddr; /* MMIO kernel io address */
void __iomem * ram_va; /* RAM kernel virtual address */ void __iomem * ramaddr; /* RAM kernel io address */
u_long io_port; /* IO port address cookie */
u_short io_ws; /* IO window size */ u_short io_ws; /* IO window size */
int irq; /* IRQ number */ int irq; /* IRQ number */
...@@ -377,29 +226,20 @@ struct sym_shcb { ...@@ -377,29 +226,20 @@ struct sym_shcb {
*/ */
#define sym_name(np) (np)->s.inst_name #define sym_name(np) (np)->s.inst_name
/*
* Data structure used as input for the NVRAM reading.
* Must resolve the IO macros and sym_name(), when
* used as sub-field 's' of another structure.
*/
struct sym_slot {
u_long base;
u_long base_2;
u_long base_c;
u_long base_2_c;
int irq;
/* port and address fields to fit INB, OUTB macros */
u_long io_port;
void __iomem * mmio_va;
char inst_name[16];
};
struct sym_nvram; struct sym_nvram;
/*
* The IO macros require a struct called 's' and are abused in sym_nvram.c
*/
struct sym_device { struct sym_device {
struct pci_dev *pdev; struct pci_dev *pdev;
struct sym_slot s; unsigned long mmio_base;
struct sym_pci_chip chip; unsigned long ram_base;
struct {
void __iomem *ioaddr;
void __iomem *ramaddr;
} s;
struct sym_chip chip;
struct sym_nvram *nvram; struct sym_nvram *nvram;
u_short device_id; u_short device_id;
u_char host_id; u_char host_id;
...@@ -412,133 +252,48 @@ struct host_data { ...@@ -412,133 +252,48 @@ struct host_data {
struct sym_hcb *ncb; struct sym_hcb *ncb;
}; };
/* static inline struct sym_hcb * sym_get_hcb(struct Scsi_Host *host)
* The driver definitions (sym_hipd.h) must know about a
* couple of things related to the memory allocator.
*/
typedef u_long m_addr_t; /* Enough bits to represent any address */
#define SYM_MEM_PAGE_ORDER 0 /* 1 PAGE maximum */
#define SYM_MEM_CLUSTER_SHIFT (PAGE_SHIFT+SYM_MEM_PAGE_ORDER)
#ifdef MODULE
#define SYM_MEM_FREE_UNUSED /* Free unused pages immediately */
#endif
typedef struct pci_dev *m_pool_ident_t;
/*
* Include driver soft definitions.
*/
#include "sym_fw.h"
#include "sym_hipd.h"
/*
* Memory allocator related stuff.
*/
#define SYM_MEM_GFP_FLAGS GFP_ATOMIC
#define SYM_MEM_WARN 1 /* Warn on failed operations */
#define sym_get_mem_cluster() \
__get_free_pages(SYM_MEM_GFP_FLAGS, SYM_MEM_PAGE_ORDER)
#define sym_free_mem_cluster(p) \
free_pages(p, SYM_MEM_PAGE_ORDER)
void *sym_calloc(int size, char *name);
void sym_mfree(void *m, int size, char *name);
/*
* We have to provide the driver memory allocator with methods for
* it to maintain virtual to bus physical address translations.
*/
#define sym_m_pool_match(mp_id1, mp_id2) (mp_id1 == mp_id2)
static __inline m_addr_t sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
{
void *vaddr = NULL;
dma_addr_t baddr = 0;
vaddr = pci_alloc_consistent(mp->dev_dmat,SYM_MEM_CLUSTER_SIZE, &baddr);
if (vaddr) {
vbp->vaddr = (m_addr_t) vaddr;
vbp->baddr = (m_addr_t) baddr;
}
return (m_addr_t) vaddr;
}
static __inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
{ {
pci_free_consistent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE, return ((struct host_data *)host->hostdata)->ncb;
(void *)vbp->vaddr, (dma_addr_t)vbp->baddr);
} }
#define sym_m_create_dma_mem_tag(mp) (0) #include "sym_fw.h"
#define sym_m_delete_dma_mem_tag(mp) do { ; } while (0) #include "sym_hipd.h"
void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name);
void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name);
m_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m);
/* /*
* Set the status field of a CAM CCB. * Set the status field of a CAM CCB.
*/ */
static __inline void static __inline void
sym_set_cam_status(struct scsi_cmnd *ccb, int status) sym_set_cam_status(struct scsi_cmnd *cmd, int status)
{ {
ccb->result &= ~(0xff << 16); cmd->result &= ~(0xff << 16);
ccb->result |= (status << 16); cmd->result |= (status << 16);
} }
/* /*
* Get the status field of a CAM CCB. * Get the status field of a CAM CCB.
*/ */
static __inline int static __inline int
sym_get_cam_status(struct scsi_cmnd *ccb) sym_get_cam_status(struct scsi_cmnd *cmd)
{ {
return ((ccb->result >> 16) & 0xff); return host_byte(cmd->result);
} }
/*
* The dma mapping is mostly handled by the
* SCSI layer and the driver glue under Linux.
*/
#define sym_data_dmamap_create(np, cp) (0)
#define sym_data_dmamap_destroy(np, cp) do { ; } while (0)
#define sym_data_dmamap_unload(np, cp) do { ; } while (0)
#define sym_data_dmamap_presync(np, cp) do { ; } while (0)
#define sym_data_dmamap_postsync(np, cp) do { ; } while (0)
/*
* Async handler for negotiations.
*/
void sym_xpt_async_nego_wide(struct sym_hcb *np, int target);
#define sym_xpt_async_nego_sync(np, target) \
sym_announce_transfer_rate(np, target)
#define sym_xpt_async_nego_ppr(np, target) \
sym_announce_transfer_rate(np, target)
/* /*
* Build CAM result for a successful IO and for a failed IO. * Build CAM result for a successful IO and for a failed IO.
*/ */
static __inline void sym_set_cam_result_ok(struct sym_hcb *np, ccb_p cp, int resid) static __inline void sym_set_cam_result_ok(struct sym_ccb *cp, struct scsi_cmnd *cmd, int resid)
{ {
struct scsi_cmnd *cmd = cp->cam_ccb;
cmd->resid = resid; cmd->resid = resid;
cmd->result = (((DID_OK) << 16) + ((cp->ssss_status) & 0x7f)); cmd->result = (((DID_OK) << 16) + ((cp->ssss_status) & 0x7f));
} }
void sym_set_cam_result_error(struct sym_hcb *np, ccb_p cp, int resid); void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid);
/*
* Other O/S specific methods.
*/
#define sym_cam_target_id(ccb) (ccb)->target
#define sym_cam_target_lun(ccb) (ccb)->lun
#define sym_freeze_cam_ccb(ccb) do { ; } while (0)
void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb); void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb);
void sym_print_addr (ccb_p cp); #define sym_print_addr(cmd, arg...) dev_info(&cmd->device->sdev_gendev , ## arg)
void sym_xpt_async_bus_reset(struct sym_hcb *np); void sym_xpt_async_bus_reset(struct sym_hcb *np);
void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target); void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target);
int sym_setup_data_and_start (struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp); int sym_setup_data_and_start (struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp);
void sym_log_bus_error(struct sym_hcb *np); void sym_log_bus_error(struct sym_hcb *np);
void sym_sniff_inquiry(struct sym_hcb *np, struct scsi_cmnd *cmd, int resid); void sym_sniff_inquiry(struct sym_hcb *np, struct scsi_cmnd *cmd, int resid);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -188,36 +188,45 @@ ...@@ -188,36 +188,45 @@
/* /*
* Common definitions for both bus space based and legacy IO methods. * Common definitions for both bus space based and legacy IO methods.
*/ */
#define INB(r) INB_OFF(offsetof(struct sym_reg,r))
#define INW(r) INW_OFF(offsetof(struct sym_reg,r))
#define INL(r) INL_OFF(offsetof(struct sym_reg,r))
#define OUTB(r, v) OUTB_OFF(offsetof(struct sym_reg,r), (v)) #define INB_OFF(np, o) ioread8(np->s.ioaddr + (o))
#define OUTW(r, v) OUTW_OFF(offsetof(struct sym_reg,r), (v)) #define INW_OFF(np, o) ioread16(np->s.ioaddr + (o))
#define OUTL(r, v) OUTL_OFF(offsetof(struct sym_reg,r), (v)) #define INL_OFF(np, o) ioread32(np->s.ioaddr + (o))
#define OUTONB(r, m) OUTB(r, INB(r) | (m)) #define OUTB_OFF(np, o, val) iowrite8((val), np->s.ioaddr + (o))
#define OUTOFFB(r, m) OUTB(r, INB(r) & ~(m)) #define OUTW_OFF(np, o, val) iowrite16((val), np->s.ioaddr + (o))
#define OUTONW(r, m) OUTW(r, INW(r) | (m)) #define OUTL_OFF(np, o, val) iowrite32((val), np->s.ioaddr + (o))
#define OUTOFFW(r, m) OUTW(r, INW(r) & ~(m))
#define OUTONL(r, m) OUTL(r, INL(r) | (m)) #define INB(np, r) INB_OFF(np, offsetof(struct sym_reg, r))
#define OUTOFFL(r, m) OUTL(r, INL(r) & ~(m)) #define INW(np, r) INW_OFF(np, offsetof(struct sym_reg, r))
#define INL(np, r) INL_OFF(np, offsetof(struct sym_reg, r))
#define OUTB(np, r, v) OUTB_OFF(np, offsetof(struct sym_reg, r), (v))
#define OUTW(np, r, v) OUTW_OFF(np, offsetof(struct sym_reg, r), (v))
#define OUTL(np, r, v) OUTL_OFF(np, offsetof(struct sym_reg, r), (v))
#define OUTONB(np, r, m) OUTB(np, r, INB(np, r) | (m))
#define OUTOFFB(np, r, m) OUTB(np, r, INB(np, r) & ~(m))
#define OUTONW(np, r, m) OUTW(np, r, INW(np, r) | (m))
#define OUTOFFW(np, r, m) OUTW(np, r, INW(np, r) & ~(m))
#define OUTONL(np, r, m) OUTL(np, r, INL(np, r) | (m))
#define OUTOFFL(np, r, m) OUTL(np, r, INL(np, r) & ~(m))
/* /*
* We normally want the chip to have a consistent view * We normally want the chip to have a consistent view
* of driver internal data structures when we restart it. * of driver internal data structures when we restart it.
* Thus these macros. * Thus these macros.
*/ */
#define OUTL_DSP(v) \ #define OUTL_DSP(np, v) \
do { \ do { \
MEMORY_WRITE_BARRIER(); \ MEMORY_WRITE_BARRIER(); \
OUTL (nc_dsp, (v)); \ OUTL(np, nc_dsp, (v)); \
} while (0) } while (0)
#define OUTONB_STD() \ #define OUTONB_STD() \
do { \ do { \
MEMORY_WRITE_BARRIER(); \ MEMORY_WRITE_BARRIER(); \
OUTONB (nc_dcntl, (STD|NOCOM)); \ OUTONB(np, nc_dcntl, (STD|NOCOM)); \
} while (0) } while (0)
/* /*
...@@ -321,7 +330,6 @@ ...@@ -321,7 +330,6 @@
* Host adapter miscellaneous flags. * Host adapter miscellaneous flags.
*/ */
#define SYM_AVOID_BUS_RESET (1) #define SYM_AVOID_BUS_RESET (1)
#define SYM_SCAN_TARGETS_HILO (1<<1)
/* /*
* Misc. * Misc.
...@@ -334,20 +342,13 @@ ...@@ -334,20 +342,13 @@
* Gather negotiable parameters value * Gather negotiable parameters value
*/ */
struct sym_trans { struct sym_trans {
u8 scsi_version;
u8 spi_version;
u8 period; u8 period;
u8 offset; u8 offset;
u8 width; unsigned int width:1;
u8 options; /* PPR options */ unsigned int iu:1;
}; unsigned int dt:1;
unsigned int qas:1;
struct sym_tinfo { unsigned int check_nego:1;
struct sym_trans curr;
struct sym_trans goal;
#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
struct sym_trans prev;
#endif
}; };
/* /*
...@@ -398,9 +399,9 @@ struct sym_tcb { ...@@ -398,9 +399,9 @@ struct sym_tcb {
/* /*
* LUN table used by the C code. * LUN table used by the C code.
*/ */
lcb_p lun0p; /* LCB of LUN #0 (usual case) */ struct sym_lcb *lun0p; /* LCB of LUN #0 (usual case) */
#if SYM_CONF_MAX_LUN > 1 #if SYM_CONF_MAX_LUN > 1
lcb_p *lunmp; /* Other LCBs [1..MAX_LUN] */ struct sym_lcb **lunmp; /* Other LCBs [1..MAX_LUN] */
#endif #endif
/* /*
...@@ -423,16 +424,14 @@ struct sym_tcb { ...@@ -423,16 +424,14 @@ struct sym_tcb {
struct sym_stcb s; struct sym_stcb s;
#endif #endif
/* /* Transfer goal */
* Transfer capabilities (SIP) struct sym_trans tgoal;
*/
struct sym_tinfo tinfo;
/* /*
* Keep track of the CCB used for the negotiation in order * Keep track of the CCB used for the negotiation in order
* to ensure that only 1 negotiation is queued at a time. * to ensure that only 1 negotiation is queued at a time.
*/ */
ccb_p nego_cp; /* CCB used for the nego */ struct sym_ccb * nego_cp; /* CCB used for the nego */
/* /*
* Set when we want to reset the device. * Set when we want to reset the device.
...@@ -520,10 +519,8 @@ struct sym_lcb { ...@@ -520,10 +519,8 @@ struct sym_lcb {
* Optionnaly the driver can handle device queueing, * Optionnaly the driver can handle device queueing,
* and requeues internally command to redo. * and requeues internally command to redo.
*/ */
SYM_QUEHEAD SYM_QUEHEAD waiting_ccbq;
waiting_ccbq; SYM_QUEHEAD started_ccbq;
SYM_QUEHEAD
started_ccbq;
int num_sgood; int num_sgood;
u_short started_tags; u_short started_tags;
u_short started_no_tag; u_short started_no_tag;
...@@ -533,8 +530,8 @@ struct sym_lcb { ...@@ -533,8 +530,8 @@ struct sym_lcb {
#ifdef SYM_OPT_LIMIT_COMMAND_REORDERING #ifdef SYM_OPT_LIMIT_COMMAND_REORDERING
/* /*
* Optionnaly the driver can try to prevent SCSI * Optionally the driver can try to prevent SCSI
* IOs from being too much reordering. * IOs from being reordered too much.
*/ */
u_char tags_si; /* Current index to tags sum */ u_char tags_si; /* Current index to tags sum */
u_short tags_sum[2]; /* Tags sum counters */ u_short tags_sum[2]; /* Tags sum counters */
...@@ -582,9 +579,9 @@ struct sym_pmc { ...@@ -582,9 +579,9 @@ struct sym_pmc {
* LUN(s) > 0. * LUN(s) > 0.
*/ */
#if SYM_CONF_MAX_LUN <= 1 #if SYM_CONF_MAX_LUN <= 1
#define sym_lp(np, tp, lun) (!lun) ? (tp)->lun0p : NULL #define sym_lp(tp, lun) (!lun) ? (tp)->lun0p : NULL
#else #else
#define sym_lp(np, tp, lun) \ #define sym_lp(tp, lun) \
(!lun) ? (tp)->lun0p : (tp)->lunmp ? (tp)->lunmp[(lun)] : NULL (!lun) ? (tp)->lun0p : (tp)->lunmp ? (tp)->lunmp[(lun)] : NULL
#endif #endif
...@@ -749,12 +746,10 @@ struct sym_ccb { ...@@ -749,12 +746,10 @@ struct sym_ccb {
/* /*
* Pointer to CAM ccb and related stuff. * Pointer to CAM ccb and related stuff.
*/ */
struct scsi_cmnd *cam_ccb; /* CAM scsiio ccb */ struct scsi_cmnd *cmd; /* CAM scsiio ccb */
u8 cdb_buf[16]; /* Copy of CDB */ u8 cdb_buf[16]; /* Copy of CDB */
u8 *sns_bbuf; /* Bounce buffer for sense data */ #define SYM_SNS_BBUF_LEN 32
#ifndef SYM_SNS_BBUF_LEN u8 sns_bbuf[SYM_SNS_BBUF_LEN]; /* Bounce buffer for sense data */
#define SYM_SNS_BBUF_LEN (32)
#endif
int data_len; /* Total data length */ int data_len; /* Total data length */
int segments; /* Number of SG segments */ int segments; /* Number of SG segments */
...@@ -787,12 +782,6 @@ struct sym_ccb { ...@@ -787,12 +782,6 @@ struct sym_ccb {
u_char sv_xerr_status; /* Saved extended status */ u_char sv_xerr_status; /* Saved extended status */
int sv_resid; /* Saved residual */ int sv_resid; /* Saved residual */
/*
* O/S specific data structure.
*/
#ifdef SYM_HAVE_SCCB
struct sym_sccb s;
#endif
/* /*
* Other fields. * Other fields.
*/ */
...@@ -801,9 +790,8 @@ struct sym_ccb { ...@@ -801,9 +790,8 @@ struct sym_ccb {
/* NO_TAG means no tag */ /* NO_TAG means no tag */
u_char target; u_char target;
u_char lun; u_char lun;
ccb_p link_ccbh; /* Host adapter CCB hash chain */ struct sym_ccb *link_ccbh; /* Host adapter CCB hash chain */
SYM_QUEHEAD SYM_QUEHEAD link_ccbq; /* Link to free/busy CCB queue */
link_ccbq; /* Link to free/busy CCB queue */
u32 startp; /* Initial data pointer */ u32 startp; /* Initial data pointer */
u32 goalp; /* Expected last data pointer */ u32 goalp; /* Expected last data pointer */
#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN #ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
...@@ -812,8 +800,7 @@ struct sym_ccb { ...@@ -812,8 +800,7 @@ struct sym_ccb {
int ext_sg; /* Extreme data pointer, used */ int ext_sg; /* Extreme data pointer, used */
int ext_ofs; /* to calculate the residual. */ int ext_ofs; /* to calculate the residual. */
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
SYM_QUEHEAD SYM_QUEHEAD link2_ccbq; /* Link for device queueing */
link2_ccbq; /* Link for device queueing */
u_char started; /* CCB queued to the squeue */ u_char started; /* CCB queued to the squeue */
#endif #endif
u_char to_abort; /* Want this IO to be aborted */ u_char to_abort; /* Want this IO to be aborted */
...@@ -830,6 +817,8 @@ struct sym_ccb { ...@@ -830,6 +817,8 @@ struct sym_ccb {
#define sym_goalp(cp) (cp->goalp) #define sym_goalp(cp) (cp->goalp)
#endif #endif
typedef struct device *m_pool_ident_t;
/* /*
* Host Control Block * Host Control Block
*/ */
...@@ -1005,7 +994,7 @@ struct sym_hcb { ...@@ -1005,7 +994,7 @@ struct sym_hcb {
/* /*
* CCB lists and queue. * CCB lists and queue.
*/ */
ccb_p *ccbh; /* CCBs hashed by DSA value */ struct sym_ccb **ccbh; /* CCBs hashed by DSA value */
/* CCB_HASH_SIZE lists of CCBs */ /* CCB_HASH_SIZE lists of CCBs */
SYM_QUEHEAD free_ccbq; /* Queue of available CCBs */ SYM_QUEHEAD free_ccbq; /* Queue of available CCBs */
SYM_QUEHEAD busy_ccbq; /* Queue of busy CCBs */ SYM_QUEHEAD busy_ccbq; /* Queue of busy CCBs */
...@@ -1037,7 +1026,7 @@ struct sym_hcb { ...@@ -1037,7 +1026,7 @@ struct sym_hcb {
#ifdef SYM_CONF_IARB_SUPPORT #ifdef SYM_CONF_IARB_SUPPORT
u_short iarb_max; /* Max. # consecutive IARB hints*/ u_short iarb_max; /* Max. # consecutive IARB hints*/
u_short iarb_count; /* Actual # of these hints */ u_short iarb_count; /* Actual # of these hints */
ccb_p last_cp; struct sym_ccb * last_cp;
#endif #endif
/* /*
...@@ -1068,41 +1057,31 @@ struct sym_hcb { ...@@ -1068,41 +1057,31 @@ struct sym_hcb {
/* /*
* FIRMWARES (sym_fw.c) * FIRMWARES (sym_fw.c)
*/ */
struct sym_fw * sym_find_firmware(struct sym_pci_chip *chip); struct sym_fw * sym_find_firmware(struct sym_chip *chip);
void sym_fw_bind_script (struct sym_hcb *np, u32 *start, int len); void sym_fw_bind_script(struct sym_hcb *np, u32 *start, int len);
/* /*
* Driver methods called from O/S specific code. * Driver methods called from O/S specific code.
*/ */
char *sym_driver_name(void); char *sym_driver_name(void);
void sym_print_xerr(ccb_p cp, int x_status); void sym_print_xerr(struct scsi_cmnd *cmd, int x_status);
int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int); int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int);
struct sym_pci_chip * struct sym_chip *sym_lookup_chip_table(u_short device_id, u_char revision);
sym_lookup_pci_chip_table (u_short device_id, u_char revision); void sym_put_start_queue(struct sym_hcb *np, struct sym_ccb *cp);
void sym_put_start_queue(struct sym_hcb *np, ccb_p cp);
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn); void sym_start_next_ccbs(struct sym_hcb *np, struct sym_lcb *lp, int maxn);
#endif #endif
void sym_start_up (struct sym_hcb *np, int reason); void sym_start_up(struct sym_hcb *np, int reason);
void sym_interrupt (struct sym_hcb *np); void sym_interrupt(struct sym_hcb *np);
int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task); int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task);
ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order); struct sym_ccb *sym_get_ccb(struct sym_hcb *np, struct scsi_cmnd *cmd, u_char tag_order);
void sym_free_ccb (struct sym_hcb *np, ccb_p cp); void sym_free_ccb(struct sym_hcb *np, struct sym_ccb *cp);
lcb_p sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln); struct sym_lcb *sym_alloc_lcb(struct sym_hcb *np, u_char tn, u_char ln);
int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp); int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, struct sym_ccb *cp);
int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out); int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out);
int sym_abort_ccb(struct sym_hcb *np, ccb_p cp, int timed_out);
int sym_reset_scsi_target(struct sym_hcb *np, int target); int sym_reset_scsi_target(struct sym_hcb *np, int target);
void sym_hcb_free(struct sym_hcb *np); void sym_hcb_free(struct sym_hcb *np);
int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvram); int sym_hcb_attach(struct Scsi_Host *shost, struct sym_fw *fw, struct sym_nvram *nvram);
/*
* Optionnaly, the driver may provide a function
* to announce transfer rate changes.
*/
#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
void sym_announce_transfer_rate(struct sym_hcb *np, int target);
#endif
/* /*
* Build a scatter/gather entry. * Build a scatter/gather entry.
...@@ -1169,7 +1148,7 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np, ...@@ -1169,7 +1148,7 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np,
case CAM_DIR_UNKNOWN: case CAM_DIR_UNKNOWN:
#endif #endif
case CAM_DIR_OUT: case CAM_DIR_OUT:
goalp = SCRIPTA_BA (np, data_out2) + 8; goalp = SCRIPTA_BA(np, data_out2) + 8;
lastp = goalp - 8 - (cp->segments * (2*4)); lastp = goalp - 8 - (cp->segments * (2*4));
#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN #ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
cp->wgoalp = cpu_to_scr(goalp); cp->wgoalp = cpu_to_scr(goalp);
...@@ -1182,7 +1161,7 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np, ...@@ -1182,7 +1161,7 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np,
#endif #endif
case CAM_DIR_IN: case CAM_DIR_IN:
cp->host_flags |= HF_DATA_IN; cp->host_flags |= HF_DATA_IN;
goalp = SCRIPTA_BA (np, data_in2) + 8; goalp = SCRIPTA_BA(np, data_in2) + 8;
lastp = goalp - 8 - (cp->segments * (2*4)); lastp = goalp - 8 - (cp->segments * (2*4));
break; break;
case CAM_DIR_NONE: case CAM_DIR_NONE:
...@@ -1190,7 +1169,7 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np, ...@@ -1190,7 +1169,7 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np,
#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN #ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
cp->host_flags |= HF_DATA_IN; cp->host_flags |= HF_DATA_IN;
#endif #endif
lastp = goalp = SCRIPTB_BA (np, no_data); lastp = goalp = SCRIPTB_BA(np, no_data);
break; break;
} }
...@@ -1207,7 +1186,7 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np, ...@@ -1207,7 +1186,7 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np,
* If direction is unknown, start at data_io. * If direction is unknown, start at data_io.
*/ */
if (dir == CAM_DIR_UNKNOWN) if (dir == CAM_DIR_UNKNOWN)
cp->phys.head.savep = cpu_to_scr(SCRIPTB_BA (np, data_io)); cp->phys.head.savep = cpu_to_scr(SCRIPTB_BA(np, data_io));
#endif #endif
} }
...@@ -1215,6 +1194,17 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np, ...@@ -1215,6 +1194,17 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np,
* MEMORY ALLOCATOR. * MEMORY ALLOCATOR.
*/ */
#define SYM_MEM_PAGE_ORDER 0 /* 1 PAGE maximum */
#define SYM_MEM_CLUSTER_SHIFT (PAGE_SHIFT+SYM_MEM_PAGE_ORDER)
#define SYM_MEM_FREE_UNUSED /* Free unused pages immediately */
#define SYM_MEM_WARN 1 /* Warn on failed operations */
#define sym_get_mem_cluster() \
(void *) __get_free_pages(GFP_ATOMIC, SYM_MEM_PAGE_ORDER)
#define sym_free_mem_cluster(p) \
free_pages((unsigned long)p, SYM_MEM_PAGE_ORDER)
/* /*
* Link between free memory chunks of a given size. * Link between free memory chunks of a given size.
*/ */
...@@ -1228,11 +1218,8 @@ typedef struct sym_m_link { ...@@ -1228,11 +1218,8 @@ typedef struct sym_m_link {
*/ */
typedef struct sym_m_vtob { /* Virtual to Bus address translation */ typedef struct sym_m_vtob { /* Virtual to Bus address translation */
struct sym_m_vtob *next; struct sym_m_vtob *next;
#ifdef SYM_HAVE_M_SVTOB void *vaddr; /* Virtual address */
struct sym_m_svtob s; /* OS specific data structure */ dma_addr_t baddr; /* Bus physical address */
#endif
m_addr_t vaddr; /* Virtual address */
m_addr_t baddr; /* Bus physical address */
} *m_vtob_p; } *m_vtob_p;
/* Hash this stuff a bit to speed up translations */ /* Hash this stuff a bit to speed up translations */
...@@ -1240,7 +1227,7 @@ typedef struct sym_m_vtob { /* Virtual to Bus address translation */ ...@@ -1240,7 +1227,7 @@ typedef struct sym_m_vtob { /* Virtual to Bus address translation */
#define VTOB_HASH_SIZE (1UL << VTOB_HASH_SHIFT) #define VTOB_HASH_SIZE (1UL << VTOB_HASH_SHIFT)
#define VTOB_HASH_MASK (VTOB_HASH_SIZE-1) #define VTOB_HASH_MASK (VTOB_HASH_SIZE-1)
#define VTOB_HASH_CODE(m) \ #define VTOB_HASH_CODE(m) \
((((m_addr_t) (m)) >> SYM_MEM_CLUSTER_SHIFT) & VTOB_HASH_MASK) ((((unsigned long)(m)) >> SYM_MEM_CLUSTER_SHIFT) & VTOB_HASH_MASK)
/* /*
* Memory pool of a given kind. * Memory pool of a given kind.
...@@ -1253,35 +1240,25 @@ typedef struct sym_m_vtob { /* Virtual to Bus address translation */ ...@@ -1253,35 +1240,25 @@ typedef struct sym_m_vtob { /* Virtual to Bus address translation */
*/ */
typedef struct sym_m_pool { typedef struct sym_m_pool {
m_pool_ident_t dev_dmat; /* Identifies the pool (see above) */ m_pool_ident_t dev_dmat; /* Identifies the pool (see above) */
m_addr_t (*get_mem_cluster)(struct sym_m_pool *); void * (*get_mem_cluster)(struct sym_m_pool *);
#ifdef SYM_MEM_FREE_UNUSED #ifdef SYM_MEM_FREE_UNUSED
void (*free_mem_cluster)(struct sym_m_pool *, m_addr_t); void (*free_mem_cluster)(struct sym_m_pool *, void *);
#endif #endif
#define M_GET_MEM_CLUSTER() mp->get_mem_cluster(mp) #define M_GET_MEM_CLUSTER() mp->get_mem_cluster(mp)
#define M_FREE_MEM_CLUSTER(p) mp->free_mem_cluster(mp, p) #define M_FREE_MEM_CLUSTER(p) mp->free_mem_cluster(mp, p)
#ifdef SYM_HAVE_M_SPOOL
struct sym_m_spool s; /* OS specific data structure */
#endif
int nump; int nump;
m_vtob_p vtob[VTOB_HASH_SIZE]; m_vtob_p vtob[VTOB_HASH_SIZE];
struct sym_m_pool *next; struct sym_m_pool *next;
struct sym_m_link h[SYM_MEM_CLUSTER_SHIFT - SYM_MEM_SHIFT + 1]; struct sym_m_link h[SYM_MEM_CLUSTER_SHIFT - SYM_MEM_SHIFT + 1];
} *m_pool_p; } *m_pool_p;
/*
* Alloc and free non DMAable memory.
*/
void sym_mfree_unlocked(void *ptr, int size, char *name);
void *sym_calloc_unlocked(int size, char *name);
/* /*
* Alloc, free and translate addresses to bus physical * Alloc, free and translate addresses to bus physical
* for DMAable memory. * for DMAable memory.
*/ */
void *__sym_calloc_dma_unlocked(m_pool_ident_t dev_dmat, int size, char *name); void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name);
void void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name);
__sym_mfree_dma_unlocked(m_pool_ident_t dev_dmat, void *m,int size, char *name); dma_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m);
u32 __vtobus_unlocked(m_pool_ident_t dev_dmat, void *m);
/* /*
* Verbs used by the driver code for DMAable memory handling. * Verbs used by the driver code for DMAable memory handling.
...@@ -1295,15 +1272,33 @@ u32 __vtobus_unlocked(m_pool_ident_t dev_dmat, void *m); ...@@ -1295,15 +1272,33 @@ u32 __vtobus_unlocked(m_pool_ident_t dev_dmat, void *m);
__sym_mfree_dma(np->bus_dmat, _uvptv_(p), l, n) __sym_mfree_dma(np->bus_dmat, _uvptv_(p), l, n)
#define sym_calloc_dma(l, n) _sym_calloc_dma(np, l, n) #define sym_calloc_dma(l, n) _sym_calloc_dma(np, l, n)
#define sym_mfree_dma(p, l, n) _sym_mfree_dma(np, p, l, n) #define sym_mfree_dma(p, l, n) _sym_mfree_dma(np, p, l, n)
#define _vtobus(np, p) __vtobus(np->bus_dmat, _uvptv_(p)) #define vtobus(p) __vtobus(np->bus_dmat, _uvptv_(p))
#define vtobus(p) _vtobus(np, p)
/* /*
* Override some function names. * We have to provide the driver memory allocator with methods for
* it to maintain virtual to bus physical address translations.
*/ */
#define PRINT_ADDR sym_print_addr
#define PRINT_TARGET sym_print_target #define sym_m_pool_match(mp_id1, mp_id2) (mp_id1 == mp_id2)
#define PRINT_LUN sym_print_lun
#define UDELAY sym_udelay static __inline void *sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
{
void *vaddr = NULL;
dma_addr_t baddr = 0;
vaddr = dma_alloc_coherent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE, &baddr,
GFP_ATOMIC);
if (vaddr) {
vbp->vaddr = vaddr;
vbp->baddr = baddr;
}
return vaddr;
}
static __inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
{
dma_free_coherent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE, vbp->vaddr,
vbp->baddr);
}
#endif /* SYM_HIPD_H */ #endif /* SYM_HIPD_H */
...@@ -66,7 +66,7 @@ static void *___sym_malloc(m_pool_p mp, int size) ...@@ -66,7 +66,7 @@ static void *___sym_malloc(m_pool_p mp, int size)
int i = 0; int i = 0;
int s = (1 << SYM_MEM_SHIFT); int s = (1 << SYM_MEM_SHIFT);
int j; int j;
m_addr_t a; void *a;
m_link_p h = mp->h; m_link_p h = mp->h;
if (size > SYM_MEM_CLUSTER_SIZE) if (size > SYM_MEM_CLUSTER_SIZE)
...@@ -88,7 +88,7 @@ static void *___sym_malloc(m_pool_p mp, int size) ...@@ -88,7 +88,7 @@ static void *___sym_malloc(m_pool_p mp, int size)
++j; ++j;
s <<= 1; s <<= 1;
} }
a = (m_addr_t) h[j].next; a = h[j].next;
if (a) { if (a) {
h[j].next = h[j].next->next; h[j].next = h[j].next->next;
while (j > i) { while (j > i) {
...@@ -101,7 +101,7 @@ static void *___sym_malloc(m_pool_p mp, int size) ...@@ -101,7 +101,7 @@ static void *___sym_malloc(m_pool_p mp, int size)
#ifdef DEBUG #ifdef DEBUG
printf("___sym_malloc(%d) = %p\n", size, (void *) a); printf("___sym_malloc(%d) = %p\n", size, (void *) a);
#endif #endif
return (void *) a; return a;
} }
/* /*
...@@ -112,7 +112,7 @@ static void ___sym_mfree(m_pool_p mp, void *ptr, int size) ...@@ -112,7 +112,7 @@ static void ___sym_mfree(m_pool_p mp, void *ptr, int size)
int i = 0; int i = 0;
int s = (1 << SYM_MEM_SHIFT); int s = (1 << SYM_MEM_SHIFT);
m_link_p q; m_link_p q;
m_addr_t a, b; unsigned long a, b;
m_link_p h = mp->h; m_link_p h = mp->h;
#ifdef DEBUG #ifdef DEBUG
...@@ -127,12 +127,12 @@ static void ___sym_mfree(m_pool_p mp, void *ptr, int size) ...@@ -127,12 +127,12 @@ static void ___sym_mfree(m_pool_p mp, void *ptr, int size)
++i; ++i;
} }
a = (m_addr_t) ptr; a = (unsigned long)ptr;
while (1) { while (1) {
if (s == SYM_MEM_CLUSTER_SIZE) { if (s == SYM_MEM_CLUSTER_SIZE) {
#ifdef SYM_MEM_FREE_UNUSED #ifdef SYM_MEM_FREE_UNUSED
M_FREE_MEM_CLUSTER(a); M_FREE_MEM_CLUSTER((void *)a);
#else #else
((m_link_p) a)->next = h[i].next; ((m_link_p) a)->next = h[i].next;
h[i].next = (m_link_p) a; h[i].next = (m_link_p) a;
...@@ -194,58 +194,40 @@ static void __sym_mfree(m_pool_p mp, void *ptr, int size, char *name) ...@@ -194,58 +194,40 @@ static void __sym_mfree(m_pool_p mp, void *ptr, int size, char *name)
* With DMA abstraction, we use functions (methods), to * With DMA abstraction, we use functions (methods), to
* distinguish between non DMAable memory and DMAable memory. * distinguish between non DMAable memory and DMAable memory.
*/ */
static m_addr_t ___mp0_get_mem_cluster(m_pool_p mp) static void *___mp0_get_mem_cluster(m_pool_p mp)
{ {
m_addr_t m = (m_addr_t) sym_get_mem_cluster(); void *m = sym_get_mem_cluster();
if (m) if (m)
++mp->nump; ++mp->nump;
return m; return m;
} }
#ifdef SYM_MEM_FREE_UNUSED #ifdef SYM_MEM_FREE_UNUSED
static void ___mp0_free_mem_cluster(m_pool_p mp, m_addr_t m) static void ___mp0_free_mem_cluster(m_pool_p mp, void *m)
{ {
sym_free_mem_cluster(m); sym_free_mem_cluster(m);
--mp->nump; --mp->nump;
} }
#endif
#ifdef SYM_MEM_FREE_UNUSED
static struct sym_m_pool mp0 =
{NULL, ___mp0_get_mem_cluster, ___mp0_free_mem_cluster};
#else #else
static struct sym_m_pool mp0 = #define ___mp0_free_mem_cluster NULL
{NULL, ___mp0_get_mem_cluster};
#endif #endif
/* static struct sym_m_pool mp0 = {
* Actual memory allocation routine for non-DMAed memory. NULL,
*/ ___mp0_get_mem_cluster,
void *sym_calloc_unlocked(int size, char *name) ___mp0_free_mem_cluster
{ };
void *m;
m = __sym_calloc(&mp0, size, name);
return m;
}
/*
* Its counter-part.
*/
void sym_mfree_unlocked(void *ptr, int size, char *name)
{
__sym_mfree(&mp0, ptr, size, name);
}
/* /*
* Methods that maintains DMAable pools according to user allocations. * Methods that maintains DMAable pools according to user allocations.
* New pools are created on the fly when a new pool id is provided. * New pools are created on the fly when a new pool id is provided.
* They are deleted on the fly when they get emptied. * They are deleted on the fly when they get emptied.
*/ */
/* Get a memory cluster that matches the DMA contraints of a given pool */ /* Get a memory cluster that matches the DMA constraints of a given pool */
static m_addr_t ___get_dma_mem_cluster(m_pool_p mp) static void * ___get_dma_mem_cluster(m_pool_p mp)
{ {
m_vtob_p vbp; m_vtob_p vbp;
m_addr_t vaddr; void *vaddr;
vbp = __sym_calloc(&mp0, sizeof(*vbp), "VTOB"); vbp = __sym_calloc(&mp0, sizeof(*vbp), "VTOB");
if (!vbp) if (!vbp)
...@@ -257,16 +239,15 @@ static m_addr_t ___get_dma_mem_cluster(m_pool_p mp) ...@@ -257,16 +239,15 @@ static m_addr_t ___get_dma_mem_cluster(m_pool_p mp)
vbp->next = mp->vtob[hc]; vbp->next = mp->vtob[hc];
mp->vtob[hc] = vbp; mp->vtob[hc] = vbp;
++mp->nump; ++mp->nump;
return (m_addr_t) vaddr;
} }
return vaddr; return vaddr;
out_err: out_err:
return 0; return NULL;
} }
#ifdef SYM_MEM_FREE_UNUSED #ifdef SYM_MEM_FREE_UNUSED
/* Free a memory cluster and associated resources for DMA */ /* Free a memory cluster and associated resources for DMA */
static void ___free_dma_mem_cluster(m_pool_p mp, m_addr_t m) static void ___free_dma_mem_cluster(m_pool_p mp, void *m)
{ {
m_vtob_p *vbpp, vbp; m_vtob_p *vbpp, vbp;
int hc = VTOB_HASH_CODE(m); int hc = VTOB_HASH_CODE(m);
...@@ -297,23 +278,17 @@ static __inline m_pool_p ___get_dma_pool(m_pool_ident_t dev_dmat) ...@@ -297,23 +278,17 @@ static __inline m_pool_p ___get_dma_pool(m_pool_ident_t dev_dmat)
/* Create a new memory DMAable pool (when fetch failed) */ /* Create a new memory DMAable pool (when fetch failed) */
static m_pool_p ___cre_dma_pool(m_pool_ident_t dev_dmat) static m_pool_p ___cre_dma_pool(m_pool_ident_t dev_dmat)
{ {
m_pool_p mp = NULL; m_pool_p mp = __sym_calloc(&mp0, sizeof(*mp), "MPOOL");
mp = __sym_calloc(&mp0, sizeof(*mp), "MPOOL");
if (mp) { if (mp) {
mp->dev_dmat = dev_dmat; mp->dev_dmat = dev_dmat;
if (!sym_m_create_dma_mem_tag(mp)) { mp->get_mem_cluster = ___get_dma_mem_cluster;
mp->get_mem_cluster = ___get_dma_mem_cluster;
#ifdef SYM_MEM_FREE_UNUSED #ifdef SYM_MEM_FREE_UNUSED
mp->free_mem_cluster = ___free_dma_mem_cluster; mp->free_mem_cluster = ___free_dma_mem_cluster;
#endif #endif
mp->next = mp0.next; mp->next = mp0.next;
mp0.next = mp; mp0.next = mp;
return mp; return mp;
}
} }
if (mp)
__sym_mfree(&mp0, mp, sizeof(*mp), "MPOOL");
return NULL; return NULL;
} }
...@@ -327,68 +302,81 @@ static void ___del_dma_pool(m_pool_p p) ...@@ -327,68 +302,81 @@ static void ___del_dma_pool(m_pool_p p)
pp = &(*pp)->next; pp = &(*pp)->next;
if (*pp) { if (*pp) {
*pp = (*pp)->next; *pp = (*pp)->next;
sym_m_delete_dma_mem_tag(p);
__sym_mfree(&mp0, p, sizeof(*p), "MPOOL"); __sym_mfree(&mp0, p, sizeof(*p), "MPOOL");
} }
} }
#endif #endif
/* This lock protects only the memory allocation/free. */
static DEFINE_SPINLOCK(sym53c8xx_lock);
/* /*
* Actual allocator for DMAable memory. * Actual allocator for DMAable memory.
*/ */
void *__sym_calloc_dma_unlocked(m_pool_ident_t dev_dmat, int size, char *name) void *__sym_calloc_dma(m_pool_ident_t dev_dmat, int size, char *name)
{ {
unsigned long flags;
m_pool_p mp; m_pool_p mp;
void *m = NULL; void *m = NULL;
spin_lock_irqsave(&sym53c8xx_lock, flags);
mp = ___get_dma_pool(dev_dmat); mp = ___get_dma_pool(dev_dmat);
if (!mp) if (!mp)
mp = ___cre_dma_pool(dev_dmat); mp = ___cre_dma_pool(dev_dmat);
if (mp) if (!mp)
m = __sym_calloc(mp, size, name); goto out;
m = __sym_calloc(mp, size, name);
#ifdef SYM_MEM_FREE_UNUSED #ifdef SYM_MEM_FREE_UNUSED
if (mp && !mp->nump) if (!mp->nump)
___del_dma_pool(mp); ___del_dma_pool(mp);
#endif #endif
out:
spin_unlock_irqrestore(&sym53c8xx_lock, flags);
return m; return m;
} }
/* void __sym_mfree_dma(m_pool_ident_t dev_dmat, void *m, int size, char *name)
* Its counter-part.
*/
void
__sym_mfree_dma_unlocked(m_pool_ident_t dev_dmat, void *m, int size, char *name)
{ {
unsigned long flags;
m_pool_p mp; m_pool_p mp;
spin_lock_irqsave(&sym53c8xx_lock, flags);
mp = ___get_dma_pool(dev_dmat); mp = ___get_dma_pool(dev_dmat);
if (mp) if (!mp)
__sym_mfree(mp, m, size, name); goto out;
__sym_mfree(mp, m, size, name);
#ifdef SYM_MEM_FREE_UNUSED #ifdef SYM_MEM_FREE_UNUSED
if (mp && !mp->nump) if (!mp->nump)
___del_dma_pool(mp); ___del_dma_pool(mp);
#endif #endif
out:
spin_unlock_irqrestore(&sym53c8xx_lock, flags);
} }
/* /*
* Actual virtual to bus physical address translator * Actual virtual to bus physical address translator
* for 32 bit addressable DMAable memory. * for 32 bit addressable DMAable memory.
*/ */
u32 __vtobus_unlocked(m_pool_ident_t dev_dmat, void *m) dma_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m)
{ {
unsigned long flags;
m_pool_p mp; m_pool_p mp;
int hc = VTOB_HASH_CODE(m); int hc = VTOB_HASH_CODE(m);
m_vtob_p vp = NULL; m_vtob_p vp = NULL;
m_addr_t a = ((m_addr_t) m) & ~SYM_MEM_CLUSTER_MASK; void *a = (void *)((unsigned long)m & ~SYM_MEM_CLUSTER_MASK);
dma_addr_t b;
spin_lock_irqsave(&sym53c8xx_lock, flags);
mp = ___get_dma_pool(dev_dmat); mp = ___get_dma_pool(dev_dmat);
if (mp) { if (mp) {
vp = mp->vtob[hc]; vp = mp->vtob[hc];
while (vp && (m_addr_t) vp->vaddr != a) while (vp && vp->vaddr != a)
vp = vp->next; vp = vp->next;
} }
if (!vp) if (!vp)
panic("sym: VTOBUS FAILED!\n"); panic("sym: VTOBUS FAILED!\n");
return (u32)(vp ? vp->baddr + (((m_addr_t) m) - a) : 0); b = vp->baddr + (m - a);
spin_unlock_irqrestore(&sym53c8xx_lock, flags);
return b;
} }
/*
* Device driver for the SYMBIOS/LSILOGIC 53C8XX and 53C1010 family
* of PCI-SCSI IO processors.
*
* Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr>
*
* This driver is derived from the Linux sym53c8xx driver.
* Copyright (C) 1998-2000 Gerard Roudier
*
* The sym53c8xx driver is derived from the ncr53c8xx driver that had been
* a port of the FreeBSD ncr driver to Linux-1.2.13.
*
* The original ncr driver has been written for 386bsd and FreeBSD by
* Wolfgang Stanglmeier <wolf@cologne.de>
* Stefan Esser <se@mi.Uni-Koeln.de>
* Copyright (C) 1994 Wolfgang Stanglmeier
*
* Other major contributions:
*
* NVRAM detection and reading.
* Copyright (C) 1997 Richard Waltham <dormouse@farsrobt.demon.co.uk>
*
*-----------------------------------------------------------------------------
*
* 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 of the License, 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "sym_glue.h"
#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
/*
* Announce transfer rate if anything changed since last announcement.
*/
void sym_announce_transfer_rate(struct sym_hcb *np, int target)
{
tcb_p tp = &np->target[target];
#define __tprev tp->tinfo.prev
#define __tcurr tp->tinfo.curr
if (__tprev.options == __tcurr.options &&
__tprev.width == __tcurr.width &&
__tprev.offset == __tcurr.offset &&
!(__tprev.offset && __tprev.period != __tcurr.period))
return;
__tprev.options = __tcurr.options;
__tprev.width = __tcurr.width;
__tprev.offset = __tcurr.offset;
__tprev.period = __tcurr.period;
if (__tcurr.offset && __tcurr.period) {
u_int period, f10, mb10;
char *scsi;
period = f10 = mb10 = 0;
scsi = "FAST-5";
if (__tcurr.period <= 9) {
scsi = "FAST-80";
period = 125;
mb10 = 1600;
}
else {
if (__tcurr.period <= 11) {
scsi = "FAST-40";
period = 250;
if (__tcurr.period == 11)
period = 303;
}
else if (__tcurr.period < 25) {
scsi = "FAST-20";
if (__tcurr.period == 12)
period = 500;
}
else if (__tcurr.period <= 50) {
scsi = "FAST-10";
}
if (!period)
period = 40 * __tcurr.period;
f10 = 100000 << (__tcurr.width ? 1 : 0);
mb10 = (f10 + period/2) / period;
}
printf_info (
"%s:%d: %s %sSCSI %d.%d MB/s %s%s%s (%d.%d ns, offset %d)\n",
sym_name(np), target, scsi, __tcurr.width? "WIDE " : "",
mb10/10, mb10%10,
(__tcurr.options & PPR_OPT_DT) ? "DT" : "ST",
(__tcurr.options & PPR_OPT_IU) ? " IU" : "",
(__tcurr.options & PPR_OPT_QAS) ? " QAS" : "",
period/10, period%10, __tcurr.offset);
}
else
printf_info ("%s:%d: %sasynchronous.\n",
sym_name(np), target, __tcurr.width? "wide " : "");
}
#undef __tprev
#undef __tcurr
#endif /* SYM_OPT_ANNOUNCE_TRANSFER_RATE */
...@@ -47,7 +47,7 @@ static u_char Tekram_boot_delay[7] = {3, 5, 10, 20, 30, 60, 120}; ...@@ -47,7 +47,7 @@ static u_char Tekram_boot_delay[7] = {3, 5, 10, 20, 30, 60, 120};
/* /*
* Get host setup from NVRAM. * Get host setup from NVRAM.
*/ */
void sym_nvram_setup_host(struct sym_hcb *np, struct sym_nvram *nvram) void sym_nvram_setup_host(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram)
{ {
/* /*
* Get parity checking, host ID, verbose mode * Get parity checking, host ID, verbose mode
...@@ -61,7 +61,7 @@ void sym_nvram_setup_host(struct sym_hcb *np, struct sym_nvram *nvram) ...@@ -61,7 +61,7 @@ void sym_nvram_setup_host(struct sym_hcb *np, struct sym_nvram *nvram)
if (nvram->data.Symbios.flags & SYMBIOS_VERBOSE_MSGS) if (nvram->data.Symbios.flags & SYMBIOS_VERBOSE_MSGS)
np->verbose += 1; np->verbose += 1;
if (nvram->data.Symbios.flags1 & SYMBIOS_SCAN_HI_LO) if (nvram->data.Symbios.flags1 & SYMBIOS_SCAN_HI_LO)
np->usrflags |= SYM_SCAN_TARGETS_HILO; shost->reverse_ordering = 1;
if (nvram->data.Symbios.flags2 & SYMBIOS_AVOID_BUS_RESET) if (nvram->data.Symbios.flags2 & SYMBIOS_AVOID_BUS_RESET)
np->usrflags |= SYM_AVOID_BUS_RESET; np->usrflags |= SYM_AVOID_BUS_RESET;
break; break;
...@@ -253,7 +253,7 @@ static void sym_display_Tekram_nvram(struct sym_device *np, Tekram_nvram *nvram) ...@@ -253,7 +253,7 @@ static void sym_display_Tekram_nvram(struct sym_device *np, Tekram_nvram *nvram)
static void S24C16_set_bit(struct sym_device *np, u_char write_bit, u_char *gpreg, static void S24C16_set_bit(struct sym_device *np, u_char write_bit, u_char *gpreg,
int bit_mode) int bit_mode)
{ {
UDELAY (5); udelay(5);
switch (bit_mode) { switch (bit_mode) {
case SET_BIT: case SET_BIT:
*gpreg |= write_bit; *gpreg |= write_bit;
...@@ -269,8 +269,8 @@ static void S24C16_set_bit(struct sym_device *np, u_char write_bit, u_char *gpre ...@@ -269,8 +269,8 @@ static void S24C16_set_bit(struct sym_device *np, u_char write_bit, u_char *gpre
break; break;
} }
OUTB (nc_gpreg, *gpreg); OUTB(np, nc_gpreg, *gpreg);
UDELAY (5); udelay(5);
} }
/* /*
...@@ -303,7 +303,7 @@ static void S24C16_do_bit(struct sym_device *np, u_char *read_bit, u_char write_ ...@@ -303,7 +303,7 @@ static void S24C16_do_bit(struct sym_device *np, u_char *read_bit, u_char write_
S24C16_set_bit(np, write_bit, gpreg, SET_BIT); S24C16_set_bit(np, write_bit, gpreg, SET_BIT);
S24C16_set_bit(np, 0, gpreg, SET_CLK); S24C16_set_bit(np, 0, gpreg, SET_CLK);
if (read_bit) if (read_bit)
*read_bit = INB (nc_gpreg); *read_bit = INB(np, nc_gpreg);
S24C16_set_bit(np, 0, gpreg, CLR_CLK); S24C16_set_bit(np, 0, gpreg, CLR_CLK);
S24C16_set_bit(np, 0, gpreg, CLR_BIT); S24C16_set_bit(np, 0, gpreg, CLR_BIT);
} }
...@@ -315,9 +315,9 @@ static void S24C16_do_bit(struct sym_device *np, u_char *read_bit, u_char write_ ...@@ -315,9 +315,9 @@ static void S24C16_do_bit(struct sym_device *np, u_char *read_bit, u_char write_
static void S24C16_write_ack(struct sym_device *np, u_char write_bit, u_char *gpreg, static void S24C16_write_ack(struct sym_device *np, u_char write_bit, u_char *gpreg,
u_char *gpcntl) u_char *gpcntl)
{ {
OUTB (nc_gpcntl, *gpcntl & 0xfe); OUTB(np, nc_gpcntl, *gpcntl & 0xfe);
S24C16_do_bit(np, NULL, write_bit, gpreg); S24C16_do_bit(np, NULL, write_bit, gpreg);
OUTB (nc_gpcntl, *gpcntl); OUTB(np, nc_gpcntl, *gpcntl);
} }
/* /*
...@@ -327,9 +327,9 @@ static void S24C16_write_ack(struct sym_device *np, u_char write_bit, u_char *gp ...@@ -327,9 +327,9 @@ static void S24C16_write_ack(struct sym_device *np, u_char write_bit, u_char *gp
static void S24C16_read_ack(struct sym_device *np, u_char *read_bit, u_char *gpreg, static void S24C16_read_ack(struct sym_device *np, u_char *read_bit, u_char *gpreg,
u_char *gpcntl) u_char *gpcntl)
{ {
OUTB (nc_gpcntl, *gpcntl | 0x01); OUTB(np, nc_gpcntl, *gpcntl | 0x01);
S24C16_do_bit(np, read_bit, 1, gpreg); S24C16_do_bit(np, read_bit, 1, gpreg);
OUTB (nc_gpcntl, *gpcntl); OUTB(np, nc_gpcntl, *gpcntl);
} }
/* /*
...@@ -379,13 +379,13 @@ static int sym_write_S24C16_nvram(struct sym_device *np, int offset, ...@@ -379,13 +379,13 @@ static int sym_write_S24C16_nvram(struct sym_device *np, int offset,
int x; int x;
/* save current state of GPCNTL and GPREG */ /* save current state of GPCNTL and GPREG */
old_gpreg = INB (nc_gpreg); old_gpreg = INB(np, nc_gpreg);
old_gpcntl = INB (nc_gpcntl); old_gpcntl = INB(np, nc_gpcntl);
gpcntl = old_gpcntl & 0x1c; gpcntl = old_gpcntl & 0x1c;
/* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */ /* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */
OUTB (nc_gpreg, old_gpreg); OUTB(np, nc_gpreg, old_gpreg);
OUTB (nc_gpcntl, gpcntl); OUTB(np, nc_gpcntl, gpcntl);
/* this is to set NVRAM into a known state with GPIO0/1 both low */ /* this is to set NVRAM into a known state with GPIO0/1 both low */
gpreg = old_gpreg; gpreg = old_gpreg;
...@@ -414,8 +414,8 @@ static int sym_write_S24C16_nvram(struct sym_device *np, int offset, ...@@ -414,8 +414,8 @@ static int sym_write_S24C16_nvram(struct sym_device *np, int offset,
} }
/* return GPIO0/1 to original states after having accessed NVRAM */ /* return GPIO0/1 to original states after having accessed NVRAM */
OUTB (nc_gpcntl, old_gpcntl); OUTB(np, nc_gpcntl, old_gpcntl);
OUTB (nc_gpreg, old_gpreg); OUTB(np, nc_gpreg, old_gpreg);
return 0; return 0;
} }
...@@ -433,13 +433,13 @@ static int sym_read_S24C16_nvram(struct sym_device *np, int offset, u_char *data ...@@ -433,13 +433,13 @@ static int sym_read_S24C16_nvram(struct sym_device *np, int offset, u_char *data
int x; int x;
/* save current state of GPCNTL and GPREG */ /* save current state of GPCNTL and GPREG */
old_gpreg = INB (nc_gpreg); old_gpreg = INB(np, nc_gpreg);
old_gpcntl = INB (nc_gpcntl); old_gpcntl = INB(np, nc_gpcntl);
gpcntl = old_gpcntl & 0x1c; gpcntl = old_gpcntl & 0x1c;
/* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */ /* set up GPREG & GPCNTL to set GPIO0 and GPIO1 in to known state */
OUTB (nc_gpreg, old_gpreg); OUTB(np, nc_gpreg, old_gpreg);
OUTB (nc_gpcntl, gpcntl); OUTB(np, nc_gpcntl, gpcntl);
/* this is to set NVRAM into a known state with GPIO0/1 both low */ /* this is to set NVRAM into a known state with GPIO0/1 both low */
gpreg = old_gpreg; gpreg = old_gpreg;
...@@ -475,7 +475,7 @@ static int sym_read_S24C16_nvram(struct sym_device *np, int offset, u_char *data ...@@ -475,7 +475,7 @@ static int sym_read_S24C16_nvram(struct sym_device *np, int offset, u_char *data
/* now set up GPIO0 for inputting data */ /* now set up GPIO0 for inputting data */
gpcntl |= 0x01; gpcntl |= 0x01;
OUTB (nc_gpcntl, gpcntl); OUTB(np, nc_gpcntl, gpcntl);
/* input all requested data - only part of total NVRAM */ /* input all requested data - only part of total NVRAM */
for (x = 0; x < len; x++) for (x = 0; x < len; x++)
...@@ -483,13 +483,13 @@ static int sym_read_S24C16_nvram(struct sym_device *np, int offset, u_char *data ...@@ -483,13 +483,13 @@ static int sym_read_S24C16_nvram(struct sym_device *np, int offset, u_char *data
/* finally put NVRAM back in inactive mode */ /* finally put NVRAM back in inactive mode */
gpcntl &= 0xfe; gpcntl &= 0xfe;
OUTB (nc_gpcntl, gpcntl); OUTB(np, nc_gpcntl, gpcntl);
S24C16_stop(np, &gpreg); S24C16_stop(np, &gpreg);
retv = 0; retv = 0;
out: out:
/* return GPIO0/1 to original states after having accessed NVRAM */ /* return GPIO0/1 to original states after having accessed NVRAM */
OUTB (nc_gpcntl, old_gpcntl); OUTB(np, nc_gpcntl, old_gpcntl);
OUTB (nc_gpreg, old_gpreg); OUTB(np, nc_gpreg, old_gpreg);
return retv; return retv;
} }
...@@ -546,9 +546,9 @@ static int sym_read_Symbios_nvram(struct sym_device *np, Symbios_nvram *nvram) ...@@ -546,9 +546,9 @@ static int sym_read_Symbios_nvram(struct sym_device *np, Symbios_nvram *nvram)
*/ */
static void T93C46_Clk(struct sym_device *np, u_char *gpreg) static void T93C46_Clk(struct sym_device *np, u_char *gpreg)
{ {
OUTB (nc_gpreg, *gpreg | 0x04); OUTB(np, nc_gpreg, *gpreg | 0x04);
UDELAY (2); udelay(2);
OUTB (nc_gpreg, *gpreg); OUTB(np, nc_gpreg, *gpreg);
} }
/* /*
...@@ -556,9 +556,9 @@ static void T93C46_Clk(struct sym_device *np, u_char *gpreg) ...@@ -556,9 +556,9 @@ static void T93C46_Clk(struct sym_device *np, u_char *gpreg)
*/ */
static void T93C46_Read_Bit(struct sym_device *np, u_char *read_bit, u_char *gpreg) static void T93C46_Read_Bit(struct sym_device *np, u_char *read_bit, u_char *gpreg)
{ {
UDELAY (2); udelay(2);
T93C46_Clk(np, gpreg); T93C46_Clk(np, gpreg);
*read_bit = INB (nc_gpreg); *read_bit = INB(np, nc_gpreg);
} }
/* /*
...@@ -573,8 +573,8 @@ static void T93C46_Write_Bit(struct sym_device *np, u_char write_bit, u_char *gp ...@@ -573,8 +573,8 @@ static void T93C46_Write_Bit(struct sym_device *np, u_char write_bit, u_char *gp
*gpreg |= 0x10; *gpreg |= 0x10;
OUTB (nc_gpreg, *gpreg); OUTB(np, nc_gpreg, *gpreg);
UDELAY (2); udelay(2);
T93C46_Clk(np, gpreg); T93C46_Clk(np, gpreg);
} }
...@@ -585,8 +585,8 @@ static void T93C46_Write_Bit(struct sym_device *np, u_char write_bit, u_char *gp ...@@ -585,8 +585,8 @@ static void T93C46_Write_Bit(struct sym_device *np, u_char write_bit, u_char *gp
static void T93C46_Stop(struct sym_device *np, u_char *gpreg) static void T93C46_Stop(struct sym_device *np, u_char *gpreg)
{ {
*gpreg &= 0xef; *gpreg &= 0xef;
OUTB (nc_gpreg, *gpreg); OUTB(np, nc_gpreg, *gpreg);
UDELAY (2); udelay(2);
T93C46_Clk(np, gpreg); T93C46_Clk(np, gpreg);
} }
...@@ -603,7 +603,7 @@ static void T93C46_Send_Command(struct sym_device *np, u_short write_data, ...@@ -603,7 +603,7 @@ static void T93C46_Send_Command(struct sym_device *np, u_short write_data,
for (x = 0; x < 9; x++) for (x = 0; x < 9; x++)
T93C46_Write_Bit(np, (u_char) (write_data >> (8 - x)), gpreg); T93C46_Write_Bit(np, (u_char) (write_data >> (8 - x)), gpreg);
*read_bit = INB (nc_gpreg); *read_bit = INB(np, nc_gpreg);
} }
/* /*
...@@ -657,23 +657,23 @@ static int sym_read_T93C46_nvram(struct sym_device *np, Tekram_nvram *nvram) ...@@ -657,23 +657,23 @@ static int sym_read_T93C46_nvram(struct sym_device *np, Tekram_nvram *nvram)
int retv = 1; int retv = 1;
/* save current state of GPCNTL and GPREG */ /* save current state of GPCNTL and GPREG */
old_gpreg = INB (nc_gpreg); old_gpreg = INB(np, nc_gpreg);
old_gpcntl = INB (nc_gpcntl); old_gpcntl = INB(np, nc_gpcntl);
/* set up GPREG & GPCNTL to set GPIO0/1/2/4 in to known state, 0 in, /* set up GPREG & GPCNTL to set GPIO0/1/2/4 in to known state, 0 in,
1/2/4 out */ 1/2/4 out */
gpreg = old_gpreg & 0xe9; gpreg = old_gpreg & 0xe9;
OUTB (nc_gpreg, gpreg); OUTB(np, nc_gpreg, gpreg);
gpcntl = (old_gpcntl & 0xe9) | 0x09; gpcntl = (old_gpcntl & 0xe9) | 0x09;
OUTB (nc_gpcntl, gpcntl); OUTB(np, nc_gpcntl, gpcntl);
/* input all of NVRAM, 64 words */ /* input all of NVRAM, 64 words */
retv = T93C46_Read_Data(np, (u_short *) nvram, retv = T93C46_Read_Data(np, (u_short *) nvram,
sizeof(*nvram) / sizeof(short), &gpreg); sizeof(*nvram) / sizeof(short), &gpreg);
/* return GPIO0/1/2/4 to original states after having accessed NVRAM */ /* return GPIO0/1/2/4 to original states after having accessed NVRAM */
OUTB (nc_gpcntl, old_gpcntl); OUTB(np, nc_gpcntl, old_gpcntl);
OUTB (nc_gpreg, old_gpreg); OUTB(np, nc_gpreg, old_gpreg);
return retv; return retv;
} }
...@@ -755,3 +755,17 @@ int sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp) ...@@ -755,3 +755,17 @@ int sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp)
} }
return nvp->type; return nvp->type;
} }
char *sym_nvram_type(struct sym_nvram *nvp)
{
switch (nvp->type) {
case SYM_SYMBIOS_NVRAM:
return "Symbios NVRAM";
case SYM_TEKRAM_NVRAM:
return "Tekram NVRAM";
case SYM_PARISC_PDC:
return "PA-RISC Firmware";
default:
return "No NVRAM";
}
}
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#ifndef SYM_NVRAM_H #ifndef SYM_NVRAM_H
#define SYM_NVRAM_H #define SYM_NVRAM_H
#include "sym_conf.h" #include "sym53c8xx.h"
/* /*
* Symbios NVRAM data format * Symbios NVRAM data format
...@@ -193,17 +193,22 @@ struct sym_nvram { ...@@ -193,17 +193,22 @@ struct sym_nvram {
}; };
#if SYM_CONF_NVRAM_SUPPORT #if SYM_CONF_NVRAM_SUPPORT
void sym_nvram_setup_host (struct sym_hcb *np, struct sym_nvram *nvram); void sym_nvram_setup_host(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram);
void sym_nvram_setup_target (struct sym_hcb *np, int target, struct sym_nvram *nvp); void sym_nvram_setup_target (struct sym_hcb *np, int target, struct sym_nvram *nvp);
int sym_read_nvram (struct sym_device *np, struct sym_nvram *nvp); int sym_read_nvram (struct sym_device *np, struct sym_nvram *nvp);
char *sym_nvram_type(struct sym_nvram *nvp);
#else #else
static inline void sym_nvram_setup_host(struct sym_hcb *np, struct sym_nvram *nvram) { } static inline void sym_nvram_setup_host(struct Scsi_Host *shost, struct sym_hcb *np, struct sym_nvram *nvram) { }
static inline void sym_nvram_setup_target(struct sym_hcb *np, struct sym_nvram *nvram) { } static inline void sym_nvram_setup_target(struct sym_hcb *np, struct sym_nvram *nvram) { }
static inline int sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp) static inline int sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp)
{ {
nvp->type = 0; nvp->type = 0;
return 0; return 0;
} }
static inline char *sym_nvram_type(struct sym_nvram *nvp)
{
return "No NVRAM";
}
#endif #endif
#endif /* SYM_NVRAM_H */ #endif /* SYM_NVRAM_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment