Commit aae7d141 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linux-scsi.bkbits.net/scsi-for-linus-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 8d3f5223 e47da193
......@@ -339,7 +339,8 @@ static int sg_scsi_ioctl(struct file *file, request_queue_t *q,
struct gendisk *bd_disk, Scsi_Ioctl_Command __user *sic)
{
struct request *rq;
int err, in_len, out_len, bytes, opcode, cmdlen;
int err;
unsigned int in_len, out_len, bytes, opcode, cmdlen;
char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE];
/*
......
......@@ -768,28 +768,6 @@ void aac_printf(struct aac_dev *dev, u32 val)
memset(cp, 0, 256);
}
/**
* aac_handle_aif - Handle a message from the firmware
* @dev: Which adapter this fib is from
* @fibptr: Pointer to fibptr from adapter
*
* This routine handles a driver notify fib from the adapter and
* dispatches it to the appropriate routine for handling.
*/
static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
{
struct hw_fib * hw_fib = fibptr->hw_fib;
/*
* Set the status of this FIB to be Invalid parameter.
*
* *(u32 *)fib->data = ST_INVAL;
*/
*(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
fib_adapter_complete(fibptr, sizeof(u32));
}
/**
* aac_command_thread - command processing thread
* @dev: Adapter to monitor
......@@ -859,7 +837,6 @@ int aac_command_thread(struct aac_dev * dev)
aifcmd = (struct aac_aifcmd *) hw_fib->data;
if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) {
/* Handle Driver Notify Events */
aac_handle_aif(dev, fib);
*(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
fib_adapter_complete(fib, sizeof(u32));
} else {
......@@ -870,10 +847,6 @@ int aac_command_thread(struct aac_dev * dev)
u32 time_now, time_last;
unsigned long flagv;
/* Sniff events */
if (aifcmd->command == cpu_to_le32(AifCmdEventNotify))
aac_handle_aif(dev, fib);
time_now = jiffies/HZ;
spin_lock_irqsave(&dev->fib_lock, flagv);
......
......@@ -125,14 +125,8 @@ ahc_linux_eisa_init(void)
uint32_t eisa_id;
size_t id_size;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
if (check_region(eisaBase, AHC_EISA_IOSIZE) != 0)
continue;
request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx");
#else
if (request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx") == 0)
continue;
#endif
eisa_id = 0;
id_size = sizeof(eisa_id);
......@@ -207,14 +201,8 @@ aic7770_map_registers(struct ahc_softc *ahc, u_int port)
/*
* Lock out other contenders for our i/o space.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
if (check_region(port, AHC_EISA_IOSIZE) != 0)
return (ENOMEM);
request_region(port, AHC_EISA_IOSIZE, "aic7xxx");
#else
if (request_region(port, AHC_EISA_IOSIZE, "aic7xxx") == 0)
return (ENOMEM);
#endif
ahc->tag = BUS_SPACE_PIO;
ahc->bsh.ioport = port;
return (0);
......
......@@ -831,8 +831,6 @@ static inline void ahc_linux_eisa_exit(void) {
/******************************* PCI Routines *********************************/
#ifdef CONFIG_PCI
void ahc_power_state_change(struct ahc_softc *ahc,
ahc_power_state new_state);
int ahc_linux_pci_init(void);
void ahc_linux_pci_exit(void);
int ahc_pci_map_registers(struct ahc_softc *ahc);
......
......@@ -42,12 +42,6 @@
#include "aic7xxx_osm.h"
#include "aic7xxx_pci.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
struct pci_device_id
{
};
#endif
static int ahc_linux_pci_dev_probe(struct pci_dev *pdev,
const struct pci_device_id *ent);
static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc,
......@@ -55,7 +49,6 @@ static int ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc,
static int ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
u_long *bus_addr,
uint8_t __iomem **maddr);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
static void ahc_linux_pci_dev_remove(struct pci_dev *pdev);
/* Define the macro locally since it's different for different class of chips.
......@@ -169,7 +162,6 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev)
} else
ahc_list_unlock(&l);
}
#endif /* !LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) */
static int
ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
......@@ -219,7 +211,6 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ahc = ahc_alloc(NULL, name);
if (ahc == NULL)
return (-ENOMEM);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
if (pci_enable_device(pdev)) {
ahc_free(ahc);
return (-ENODEV);
......@@ -238,14 +229,12 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
ahc->platform_data->hw_dma_mask = DMA_32BIT_MASK;
}
#endif
ahc->dev_softc = pci;
error = ahc_pci_config(ahc, entry);
if (error != 0) {
ahc_free(ahc);
return (-error);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pci_set_drvdata(pdev, ahc);
if (aic7xxx_detect_complete) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
......@@ -256,39 +245,14 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return (-ENODEV);
#endif
}
#endif
return (0);
}
int
ahc_linux_pci_init(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
/* Translate error or zero return into zero or one */
return pci_module_init(&aic7xxx_pci_driver) ? 0 : 1;
#else
struct pci_dev *pdev;
u_int class;
int found;
/* If we don't have a PCI bus, we can't find any adapters. */
if (pci_present() == 0)
return (0);
found = 0;
pdev = NULL;
class = PCI_CLASS_STORAGE_SCSI << 8;
while ((pdev = pci_find_class(class, pdev)) != NULL) {
ahc_dev_softc_t pci;
int error;
pci = pdev;
error = ahc_linux_pci_dev_probe(pdev, /*pci_devid*/NULL);
if (error == 0)
found++;
}
return (found);
#endif
}
void
......@@ -303,22 +267,11 @@ ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base)
if (aic7xxx_allow_memio == 0)
return (ENOMEM);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
*base = pci_resource_start(ahc->dev_softc, 0);
#else
*base = ahc_pci_read_config(ahc->dev_softc, PCIR_MAPS, 4);
*base &= PCI_BASE_ADDRESS_IO_MASK;
#endif
if (*base == 0)
return (ENOMEM);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
if (check_region(*base, 256) != 0)
return (ENOMEM);
request_region(*base, 256, "aic7xxx");
#else
if (request_region(*base, 256, "aic7xxx") == 0)
return (ENOMEM);
#endif
return (0);
}
......@@ -334,17 +287,13 @@ ahc_linux_pci_reserve_mem_region(struct ahc_softc *ahc,
start = pci_resource_start(ahc->dev_softc, 1);
if (start != 0) {
*bus_addr = start;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
if (request_mem_region(start, 0x1000, "aic7xxx") == 0)
error = ENOMEM;
#endif
if (error == 0) {
*maddr = ioremap_nocache(start, 256);
if (*maddr == NULL) {
error = ENOMEM;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
release_mem_region(start, 0x1000);
#endif
}
}
} else
......@@ -387,10 +336,8 @@ ahc_pci_map_registers(struct ahc_softc *ahc)
ahc_get_pci_slot(ahc->dev_softc),
ahc_get_pci_function(ahc->dev_softc));
iounmap(maddr);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
release_mem_region(ahc->platform_data->mem_busaddr,
0x1000);
#endif
ahc->bsh.maddr = NULL;
maddr = NULL;
} else
......@@ -440,41 +387,3 @@ ahc_pci_map_int(struct ahc_softc *ahc)
return (-error);
}
void
ahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pci_set_power_state(ahc->dev_softc, new_state);
#else
uint32_t cap;
u_int cap_offset;
/*
* Traverse the capability list looking for
* the power management capability.
*/
cap = 0;
cap_offset = ahc_pci_read_config(ahc->dev_softc,
PCIR_CAP_PTR, /*bytes*/1);
while (cap_offset != 0) {
cap = ahc_pci_read_config(ahc->dev_softc,
cap_offset, /*bytes*/4);
if ((cap & 0xFF) == 1
&& ((cap >> 16) & 0x3) > 0) {
uint32_t pm_control;
pm_control = ahc_pci_read_config(ahc->dev_softc,
cap_offset + 4,
/*bytes*/4);
pm_control &= ~0x3;
pm_control |= new_state;
ahc_pci_write_config(ahc->dev_softc,
cap_offset + 4,
pm_control, /*bytes*/2);
break;
}
cap_offset = (cap >> 8) & 0xFF;
}
#endif
}
......@@ -721,7 +721,7 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
ahc->chip |= AHC_PCI;
ahc->description = entry->name;
ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0);
error = ahc_pci_map_registers(ahc);
if (error != 0)
......@@ -2016,7 +2016,7 @@ static int
ahc_pci_resume(struct ahc_softc *ahc)
{
ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0);
/*
* We assume that the OS has restored our register
......
......@@ -1156,17 +1156,14 @@ scsi_show_extd_sense(unsigned char asc, unsigned char ascq)
}
/* Print sense information */
static void
print_sense_internal(const char *devclass,
const unsigned char *sense_buffer,
int sense_len,
struct request *req)
void
__scsi_print_sense(const char *name, const unsigned char *sense_buffer,
int sense_len)
{
int k, num, res;
unsigned int info;
const char *error;
const char *sense_txt;
const char *name = req->rq_disk ? req->rq_disk->disk_name : devclass;
struct scsi_sense_hdr ssh;
res = scsi_normalize_sense(sense_buffer, sense_len, &ssh);
......@@ -1254,18 +1251,25 @@ print_sense_internal(const char *devclass,
printk("\n");
}
}
EXPORT_SYMBOL(__scsi_print_sense);
void scsi_print_sense(const char *devclass, struct scsi_cmnd *cmd)
{
print_sense_internal(devclass, cmd->sense_buffer,
SCSI_SENSE_BUFFERSIZE, cmd->request);
const char *name = devclass;
if (cmd->request->rq_disk)
name = cmd->request->rq_disk->disk_name;
__scsi_print_sense(name, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
}
EXPORT_SYMBOL(scsi_print_sense);
void scsi_print_req_sense(const char *devclass, struct scsi_request *sreq)
{
print_sense_internal(devclass, sreq->sr_sense_buffer,
SCSI_SENSE_BUFFERSIZE, sreq->sr_request);
const char *name = devclass;
if (sreq->sr_request->rq_disk)
name = sreq->sr_request->rq_disk->disk_name;
__scsi_print_sense(name, sreq->sr_sense_buffer, SCSI_SENSE_BUFFERSIZE);
}
EXPORT_SYMBOL(scsi_print_req_sense);
......
......@@ -96,7 +96,6 @@
#include "scsi.h"
#include <scsi/scsi_host.h>
#include "fd_mcs.h"
#define DRIVER_VERSION "v0.2 by ZP Gu<zpg@castle.net>"
......@@ -104,14 +103,12 @@
#define DEBUG 0 /* Enable debugging output */
#define ENABLE_PARITY 1 /* Enable SCSI Parity */
#define DO_DETECT 0 /* Do device detection here (see scsi.c) */
/* END OF USER DEFINABLE OPTIONS */
#if DEBUG
#define EVERY_ACCESS 0 /* Write a line on every scsi access */
#define ERRORS_ONLY 1 /* Only write a line if there is an error */
#define DEBUG_DETECT 1 /* Debug fd_mcs_detect() */
#define DEBUG_MESSAGES 1 /* Debug MESSAGE IN phase */
#define DEBUG_ABORT 1 /* Debug abort() routine */
#define DEBUG_RESET 1 /* Debug reset() routine */
......@@ -119,7 +116,6 @@
#else
#define EVERY_ACCESS 0 /* LEAVE THESE ALONE--CHANGE THE ONES ABOVE */
#define ERRORS_ONLY 0
#define DEBUG_DETECT 0
#define DEBUG_MESSAGES 0
#define DEBUG_ABORT 0
#define DEBUG_RESET 0
......@@ -432,6 +428,7 @@ static int fd_mcs_detect(Scsi_Host_Template * tpnt)
FIFO_COUNT = user_fifo_count ? user_fifo_count : fd_mcs_adapters[loop].fifo_count;
FIFO_Size = user_fifo_size ? user_fifo_size : fd_mcs_adapters[loop].fifo_size;
/* FIXME: Do we need to keep this bit of code inside NOT_USED around at all? */
#ifdef NOT_USED
/* *************************************************** */
/* Try to toggle 32-bit mode. This only
......@@ -510,59 +507,6 @@ static int fd_mcs_detect(Scsi_Host_Template * tpnt)
outb(0, SCSI_Mode_Cntl_port);
outb(PARITY_MASK, TMC_Cntl_port);
/* done reset */
#if DO_DETECT
/* scan devices attached */
{
const int buflen = 255;
int i, j, retcode;
Scsi_Cmnd SCinit;
unsigned char do_inquiry[] = { INQUIRY, 0, 0, 0, buflen, 0 };
unsigned char do_request_sense[] = { REQUEST_SENSE,
0, 0, 0, buflen, 0
};
unsigned char do_read_capacity[] = { READ_CAPACITY,
0, 0, 0, 0, 0, 0, 0, 0, 0
};
unsigned char buf[buflen];
SCinit.request_buffer = SCinit.buffer = buf;
SCinit.request_bufflen = SCinit.bufflen = sizeof(buf) - 1;
SCinit.use_sg = 0;
SCinit.lun = 0;
SCinit.host = shpnt;
printk("fd_mcs: detection routine scanning for devices:\n");
for (i = 0; i < 8; i++) {
if (i == shpnt->this_id) /* Skip host adapter */
continue;
SCinit.target = i;
memcpy(SCinit.cmnd, do_request_sense, sizeof(do_request_sense));
retcode = fd_mcs_command(&SCinit);
if (!retcode) {
memcpy(SCinit.cmnd, do_inquiry, sizeof(do_inquiry));
retcode = fd_mcs_command(&SCinit);
if (!retcode) {
printk(" SCSI ID %d: ", i);
for (j = 8; j < (buf[4] < 32 ? buf[4] : 32); j++)
printk("%c", buf[j] >= 20 ? buf[j] : ' ');
memcpy(SCinit.cmnd, do_read_capacity, sizeof(do_read_capacity));
retcode = fd_mcs_command(&SCinit);
if (!retcode) {
unsigned long blocks, size, capacity;
blocks = (buf[0] << 24) | (buf[1] << 16)
| (buf[2] << 8) | buf[3];
size = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
capacity = +(+(blocks / 1024L) * +(size * 10L)) / 1024L;
printk("%lu MB (%lu byte blocks)\n", ((capacity + 5L) / 10L), size);
}
}
}
}
}
#endif
}
}
......
/* fd_mcs.h -- Header for Future Domain MCS 600/700 (or IBM OEM) driver
*
* fd_mcs.h v0.2 03/11/1998 ZP Gu (zpg@castle.net)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* 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.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef _FD_MCS_H
#define _FD_MCS_H
static int fd_mcs_detect(Scsi_Host_Template *);
static int fd_mcs_release(struct Scsi_Host *);
static int fd_mcs_command(Scsi_Cmnd *);
static int fd_mcs_abort(Scsi_Cmnd *);
static int fd_mcs_bus_reset(Scsi_Cmnd *);
static int fd_mcs_device_reset(Scsi_Cmnd *);
static int fd_mcs_host_reset(Scsi_Cmnd *);
static int fd_mcs_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
static int fd_mcs_biosparam(struct scsi_device *, struct block_device *,
sector_t, int *);
static const char *fd_mcs_info(struct Scsi_Host *);
#endif /* _FD_MCS_H */
This diff is collapsed.
#ifndef IRQ_HANDLED
typedef void irqreturn_t;
#define IRQ_NONE
#define IRQ_HANDLED
#endif
#ifndef MODULE_LICENSE
#define MODULE_LICENSE(x)
#endif
#ifndef SERVICE_ACTION_IN
#define SERVICE_ACTION_IN 0x9e
#endif
#ifndef READ_16
#define READ_16 0x88
#endif
#ifndef WRITE_16
#define WRITE_16 0x8a
#endif
This diff is collapsed.
......@@ -14,14 +14,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
static void gdth_do_req(Scsi_Request *srp, gdth_cmd_str *cmd,
char *cmnd, int timeout);
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#else
static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd,
char *cmnd, int timeout);
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp);
#else
static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd,
char *cmnd, int timeout);
static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp);
#endif
static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
......
......@@ -87,7 +87,7 @@ static int max_channel = 3;
static int init_timeout = 5;
static int max_requests = 50;
#define IBMVSCSI_VERSION "1.5.1"
#define IBMVSCSI_VERSION "1.5.5"
MODULE_DESCRIPTION("IBM Virtual SCSI");
MODULE_AUTHOR("Dave Boutcher");
......@@ -256,6 +256,7 @@ static void init_event_struct(struct srp_event_struct *evt_struct,
{
evt_struct->cmnd = NULL;
evt_struct->cmnd_done = NULL;
evt_struct->sync_srp = NULL;
evt_struct->crq.format = format;
evt_struct->crq.timeout = timeout;
evt_struct->done = done;
......@@ -467,7 +468,7 @@ static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
struct ibmvscsi_host_data *hostdata)
{
struct scsi_cmnd *cmnd = evt_struct->cmnd;
struct scsi_cmnd *cmnd;
u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
int rc;
......@@ -479,22 +480,15 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) &&
(atomic_dec_if_positive(&hostdata->request_limit) < 0)) {
/* See if the adapter is disabled */
if (atomic_read(&hostdata->request_limit) < 0) {
if (cmnd)
cmnd->result = DID_ERROR << 16;
if (evt_struct->cmnd_done)
evt_struct->cmnd_done(cmnd);
unmap_cmd_data(&evt_struct->iu.srp.cmd,
hostdata->dev);
free_event_struct(&hostdata->pool, evt_struct);
return 0;
} else {
printk("ibmvscsi: Warning, request_limit exceeded\n");
unmap_cmd_data(&evt_struct->iu.srp.cmd,
hostdata->dev);
free_event_struct(&hostdata->pool, evt_struct);
return SCSI_MLQUEUE_HOST_BUSY;
}
if (atomic_read(&hostdata->request_limit) < 0)
goto send_error;
printk(KERN_WARNING
"ibmvscsi: Warning, request_limit exceeded\n");
unmap_cmd_data(&evt_struct->iu.srp.cmd,
hostdata->dev);
free_event_struct(&hostdata->pool, evt_struct);
return SCSI_MLQUEUE_HOST_BUSY;
}
/* Copy the IU into the transfer area */
......@@ -511,18 +505,24 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
list_del(&evt_struct->list);
cmnd = evt_struct->cmnd;
printk(KERN_ERR "ibmvscsi: failed to send event struct rc %d\n",
rc);
unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);
free_event_struct(&hostdata->pool, evt_struct);
if (cmnd)
cmnd->result = DID_ERROR << 16;
if (evt_struct->cmnd_done)
evt_struct->cmnd_done(cmnd);
goto send_error;
}
return 0;
send_error:
unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);
if ((cmnd = evt_struct->cmnd) != NULL) {
cmnd->result = DID_ERROR << 16;
evt_struct->cmnd_done(cmnd);
} else if (evt_struct->done)
evt_struct->done(evt_struct);
free_event_struct(&hostdata->pool, evt_struct);
return 0;
}
/**
......@@ -537,6 +537,13 @@ static void handle_cmd_rsp(struct srp_event_struct *evt_struct)
struct srp_rsp *rsp = &evt_struct->xfer_iu->srp.rsp;
struct scsi_cmnd *cmnd = evt_struct->cmnd;
if (unlikely(rsp->type != SRP_RSP_TYPE)) {
if (printk_ratelimit())
printk(KERN_WARNING
"ibmvscsi: bad SRP RSP type %d\n",
rsp->type);
}
if (cmnd) {
cmnd->result = rsp->status;
if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION)
......@@ -641,11 +648,16 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct)
evt_struct->xfer_iu->mad.adapter_info.common.status);
} else {
printk("ibmvscsi: host srp version: %s, "
"host partition %s (%d), OS %d\n",
"host partition %s (%d), OS %d, max io %u\n",
hostdata->madapter_info.srp_version,
hostdata->madapter_info.partition_name,
hostdata->madapter_info.partition_number,
hostdata->madapter_info.os_type);
hostdata->madapter_info.os_type,
hostdata->madapter_info.port_max_txu[0]);
if (hostdata->madapter_info.port_max_txu[0])
hostdata->host->max_sectors =
hostdata->madapter_info.port_max_txu[0] >> 9;
}
}
......@@ -796,6 +808,10 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata)
*/
static void sync_completion(struct srp_event_struct *evt_struct)
{
/* copy the response back */
if (evt_struct->sync_srp)
*evt_struct->sync_srp = *evt_struct->xfer_iu;
complete(&evt_struct->comp);
}
......@@ -810,6 +826,8 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
struct srp_tsk_mgmt *tsk_mgmt;
struct srp_event_struct *evt;
struct srp_event_struct *tmp_evt, *found_evt;
union viosrp_iu srp_rsp;
int rsp_rc;
u16 lun = lun_from_dev(cmd->device);
/* First, find this command in our sent list so we can figure
......@@ -849,6 +867,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
printk(KERN_INFO "ibmvscsi: aborting command. lun 0x%lx, tag 0x%lx\n",
tsk_mgmt->lun, tsk_mgmt->managed_task_tag);
evt->sync_srp = &srp_rsp;
init_completion(&evt->comp);
if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
......@@ -859,6 +878,29 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
wait_for_completion(&evt->comp);
spin_lock_irq(hostdata->host->host_lock);
/* make sure we got a good response */
if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
if (printk_ratelimit())
printk(KERN_WARNING
"ibmvscsi: abort bad SRP RSP type %d\n",
srp_rsp.srp.generic.type);
return FAILED;
}
if (srp_rsp.srp.rsp.rspvalid)
rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);
else
rsp_rc = srp_rsp.srp.rsp.status;
if (rsp_rc) {
if (printk_ratelimit())
printk(KERN_WARNING
"ibmvscsi: abort code %d for task tag 0x%lx\n",
rsp_rc,
tsk_mgmt->managed_task_tag);
return FAILED;
}
/* Because we dropped the spinlock above, it's possible
* The event is no longer in our list. Make sure it didn't
* complete while we were aborting
......@@ -871,13 +913,17 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
}
}
if (found_evt == NULL) {
printk(KERN_INFO
"ibmvscsi: aborted task tag 0x%lx completed\n",
tsk_mgmt->managed_task_tag);
return SUCCESS;
}
printk(KERN_INFO
"ibmvscsi: successfully aborted task tag 0x%lx\n",
tsk_mgmt->managed_task_tag);
if (found_evt == NULL)
return SUCCESS;
cmd->result = (DID_ABORT << 16);
list_del(&found_evt->list);
unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev);
......@@ -899,6 +945,8 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
struct srp_tsk_mgmt *tsk_mgmt;
struct srp_event_struct *evt;
struct srp_event_struct *tmp_evt, *pos;
union viosrp_iu srp_rsp;
int rsp_rc;
u16 lun = lun_from_dev(cmd->device);
evt = get_event_struct(&hostdata->pool);
......@@ -923,6 +971,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
printk(KERN_INFO "ibmvscsi: resetting device. lun 0x%lx\n",
tsk_mgmt->lun);
evt->sync_srp = &srp_rsp;
init_completion(&evt->comp);
if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
......@@ -933,6 +982,29 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
wait_for_completion(&evt->comp);
spin_lock_irq(hostdata->host->host_lock);
/* make sure we got a good response */
if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
if (printk_ratelimit())
printk(KERN_WARNING
"ibmvscsi: reset bad SRP RSP type %d\n",
srp_rsp.srp.generic.type);
return FAILED;
}
if (srp_rsp.srp.rsp.rspvalid)
rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);
else
rsp_rc = srp_rsp.srp.rsp.status;
if (rsp_rc) {
if (printk_ratelimit())
printk(KERN_WARNING
"ibmvscsi: reset code %d for task tag 0x%lx\n",
rsp_rc,
tsk_mgmt->managed_task_tag);
return FAILED;
}
/* We need to find all commands for this LUN that have not yet been
* responded to, and fail them with DID_RESET
*/
......@@ -1048,6 +1120,13 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq,
return;
}
if (atomic_read(&evt_struct->free)) {
printk(KERN_ERR
"ibmvscsi: received duplicate correlation_token 0x%p!\n",
(void *)crq->IU_data_ptr);
return;
}
if (crq->format == VIOSRP_SRP_FORMAT)
atomic_add(evt_struct->xfer_iu->srp.rsp.request_limit_delta,
&hostdata->request_limit);
......@@ -1295,6 +1374,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
hostdata->host = host;
hostdata->dev = dev;
atomic_set(&hostdata->request_limit, -1);
hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */
if (ibmvscsi_init_crq_queue(&hostdata->queue, hostdata,
max_requests) != 0) {
......@@ -1326,7 +1406,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
*/
for (wait_switch = jiffies + (init_timeout * HZ);
time_before(jiffies, wait_switch) &&
atomic_read(&hostdata->request_limit) < 0;) {
atomic_read(&hostdata->request_limit) < 2;) {
msleep(10);
}
......
......@@ -67,6 +67,7 @@ struct srp_event_struct {
union viosrp_iu iu;
void (*cmnd_done) (struct scsi_cmnd *);
struct completion comp;
union viosrp_iu *sync_srp;
};
/* a pool of event structs for use */
......
......@@ -2610,23 +2610,19 @@ static int ipr_free_dump(struct ipr_ioa_cfg *ioa_cfg) { return 0; };
#endif
/**
* ipr_store_queue_depth - Change the device's queue depth
* @dev: device struct
* @buf: buffer
* ipr_change_queue_depth - Change the device's queue depth
* @sdev: scsi device struct
* @qdepth: depth to set
*
* Return value:
* number of bytes printed to buffer
* actual depth set
**/
static ssize_t ipr_store_queue_depth(struct device *dev,
const char *buf, size_t count)
static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
struct ipr_resource_entry *res;
int qdepth = simple_strtoul(buf, NULL, 10);
int tagged = 0;
unsigned long lock_flags = 0;
ssize_t len = -ENXIO;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
res = (struct ipr_resource_entry *)sdev->hostdata;
......@@ -2635,23 +2631,13 @@ static ssize_t ipr_store_queue_depth(struct device *dev,
if (ipr_is_gscsi(res) && res->tcq_active)
tagged = MSG_ORDERED_TAG;
len = strlen(buf);
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
scsi_adjust_queue_depth(sdev, tagged, qdepth);
return len;
return qdepth;
}
static struct device_attribute ipr_queue_depth_attr = {
.attr = {
.name = "queue_depth",
.mode = S_IRUSR | S_IWUSR,
},
.store = ipr_store_queue_depth
};
/**
* ipr_show_tcq_enable - Show if the device is enabled for tcqing
* @dev: device struct
......@@ -2760,7 +2746,6 @@ static struct device_attribute ipr_adapter_handle_attr = {
};
static struct device_attribute *ipr_dev_attrs[] = {
&ipr_queue_depth_attr,
&ipr_tcqing_attr,
&ipr_adapter_handle_attr,
NULL,
......@@ -3961,6 +3946,7 @@ static struct scsi_host_template driver_template = {
.slave_alloc = ipr_slave_alloc,
.slave_configure = ipr_slave_configure,
.slave_destroy = ipr_slave_destroy,
.change_queue_depth = ipr_change_queue_depth,
.bios_param = ipr_biosparam,
.can_queue = IPR_MAX_COMMANDS,
.this_id = -1,
......
......@@ -54,13 +54,33 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
#include "lasi700.h"
#include "53c700.h"
MODULE_AUTHOR("James Bottomley");
MODULE_DESCRIPTION("lasi700 SCSI Driver");
MODULE_LICENSE("GPL");
#define LASI_700_SVERSION 0x00071
#define LASI_710_SVERSION 0x00082
#define LASI700_ID_TABLE { \
.hw_type = HPHW_FIO, \
.sversion = LASI_700_SVERSION, \
.hversion = HVERSION_ANY_ID, \
.hversion_rev = HVERSION_REV_ANY_ID, \
}
#define LASI710_ID_TABLE { \
.hw_type = HPHW_FIO, \
.sversion = LASI_710_SVERSION, \
.hversion = HVERSION_ANY_ID, \
.hversion_rev = HVERSION_REV_ANY_ID, \
}
#define LASI700_CLOCK 25
#define LASI710_CLOCK 40
#define LASI_SCSI_CORE_OFFSET 0x100
static struct parisc_device_id lasi700_ids[] = {
LASI700_ID_TABLE,
LASI710_ID_TABLE,
......
/* -*- mode: c; c-basic-offset: 8 -*- */
/* PARISC LASI driver for the 53c700 chip
*
* Copyright (C) 2001 by James.Bottomley@HansenPartnership.com
**-----------------------------------------------------------------------------
**
** 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., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**-----------------------------------------------------------------------------
*/
#ifndef _LASI700_H
#define _LASI700_H
#define LASI_710_SVERSION 0x082
#define LASI_700_SVERSION 0x071
#define LASI700_ID_TABLE { \
.hw_type = HPHW_FIO, \
.sversion = LASI_700_SVERSION, \
.hversion = HVERSION_ANY_ID, \
.hversion_rev = HVERSION_REV_ANY_ID, \
}
#define LASI710_ID_TABLE { \
.hw_type = HPHW_FIO, \
.sversion = LASI_710_SVERSION, \
.hversion = HVERSION_ANY_ID, \
.hversion_rev = HVERSION_REV_ANY_ID, \
}
#define LASI700_CLOCK 25
#define LASI710_CLOCK 40
#define LASI_SCSI_CORE_OFFSET 0x100
#endif
This diff is collapsed.
/*
* $Header: /cvsroot/osst/Driver/osst.h,v 1.14 2003/12/14 14:34:38 wriede Exp $
* $Header: /cvsroot/osst/Driver/osst.h,v 1.16 2005/01/01 21:13:35 wriede Exp $
*/
#include <asm/byteorder.h>
......@@ -70,7 +70,7 @@ typedef struct {
#define BLOCK_SIZE_PAGE_LENGTH 4
#define BUFFER_FILLING_PAGE 0x33
#define BUFFER_FILLING_PAGE_LENGTH
#define BUFFER_FILLING_PAGE_LENGTH 4
#define VENDOR_IDENT_PAGE 0x36
#define VENDOR_IDENT_PAGE_LENGTH 8
......@@ -508,7 +508,7 @@ typedef struct os_header_s {
//#define OSST_MAX_SG 2
/* The OnStream tape buffer descriptor. */
typedef struct {
struct osst_buffer {
unsigned char in_use;
unsigned char dma; /* DMA-able buffer */
int buffer_size;
......@@ -525,16 +525,16 @@ typedef struct {
unsigned short sg_segs; /* number of segments in s/g list */
unsigned short orig_sg_segs; /* number of segments allocated at first try */
struct scatterlist sg[1]; /* MUST BE last item */
} OSST_buffer;
} ;
/* The OnStream tape drive descriptor */
typedef struct {
struct osst_tape {
struct scsi_driver *driver;
unsigned capacity;
Scsi_Device* device;
struct semaphore lock; /* for serialization */
struct completion wait; /* for SCSI commands */
OSST_buffer * buffer;
struct osst_buffer * buffer;
/* Drive characteristics */
unsigned char omit_blklims;
......@@ -577,6 +577,7 @@ typedef struct {
int min_block;
int max_block;
int recover_count; /* from tape opening */
int abort_count;
int write_count;
int read_count;
int recover_erreg; /* from last status call */
......@@ -623,7 +624,7 @@ typedef struct {
unsigned char last_sense[16];
#endif
struct gendisk *drive;
} OS_Scsi_Tape;
} ;
/* Values of write_type */
#define OS_WRITE_DATA 0
......
......@@ -3400,7 +3400,8 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
sp->flags |= SRB_SENT;
ha->actthreads++;
WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
(void) RD_REG_WORD(&reg->mailbox4); /* PCI posted write flush */
/* Enforce mmio write ordering; see comment in qla1280_isp_cmd(). */
mmiowb();
out:
if (status)
......@@ -3668,7 +3669,8 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp)
sp->flags |= SRB_SENT;
ha->actthreads++;
WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
(void) RD_REG_WORD(&reg->mailbox4); /* PCI posted write flush */
/* Enforce mmio write ordering; see comment in qla1280_isp_cmd(). */
mmiowb();
out:
if (status)
......@@ -3778,9 +3780,21 @@ qla1280_isp_cmd(struct scsi_qla_host *ha)
} else
ha->request_ring_ptr++;
/* Set chip new ring index. */
/*
* Update request index to mailbox4 (Request Queue In).
* The mmiowb() ensures that this write is ordered with writes by other
* CPUs. Without the mmiowb(), it is possible for the following:
* CPUA posts write of index 5 to mailbox4
* CPUA releases host lock
* CPUB acquires host lock
* CPUB posts write of index 6 to mailbox4
* On PCI bus, order reverses and write of 6 posts, then index 5,
* causing chip to issue full queue of stale commands
* The mmiowb() prevents future writes from crossing the barrier.
* See Documentation/DocBook/deviceiobook.tmpl for more information.
*/
WRT_REG_WORD(&reg->mailbox4, ha->req_ring_index);
(void) RD_REG_WORD(&reg->mailbox4); /* PCI posted write flush */
mmiowb();
LEAVE("qla1280_isp_cmd");
}
......
......@@ -1082,6 +1082,28 @@ struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *shost,
}
EXPORT_SYMBOL(__scsi_iterate_devices);
/**
* starget_for_each_device - helper to walk all devices of a target
* @starget: target whose devices we want to iterate over.
*
* This traverses over each devices of @shost. The devices have
* a reference that must be released by scsi_host_put when breaking
* out of the loop.
*/
void starget_for_each_device(struct scsi_target *starget, void * data,
void (*fn)(struct scsi_device *, void *))
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct scsi_device *sdev;
shost_for_each_device(sdev, shost) {
if ((sdev->channel == starget->channel) &&
(sdev->id == starget->id))
fn(sdev, data);
}
}
EXPORT_SYMBOL(starget_for_each_device);
/**
* scsi_device_lookup - find a device given the host (UNLOCKED)
* @shost: SCSI host pointer
......
......@@ -1782,31 +1782,29 @@ scsi_device_resume(struct scsi_device *sdev)
}
EXPORT_SYMBOL(scsi_device_resume);
static int
device_quiesce_fn(struct device *dev, void *data)
static void
device_quiesce_fn(struct scsi_device *sdev, void *data)
{
scsi_device_quiesce(to_scsi_device(dev));
return 0;
scsi_device_quiesce(sdev);
}
void
scsi_target_quiesce(struct scsi_target *starget)
{
device_for_each_child(&starget->dev, NULL, device_quiesce_fn);
starget_for_each_device(starget, NULL, device_quiesce_fn);
}
EXPORT_SYMBOL(scsi_target_quiesce);
static int
device_resume_fn(struct device *dev, void *data)
static void
device_resume_fn(struct scsi_device *sdev, void *data)
{
scsi_device_resume(to_scsi_device(dev));
return 0;
scsi_device_resume(sdev);
}
void
scsi_target_resume(struct scsi_target *starget)
{
device_for_each_child(&starget->dev, NULL, device_resume_fn);
starget_for_each_device(starget, NULL, device_resume_fn);
}
EXPORT_SYMBOL(scsi_target_resume);
......
......@@ -270,6 +270,16 @@ static int fc_setup_host_transport_attrs(struct Scsi_Host *shost)
sizeof(fc_host_symbolic_name(shost)));
fc_host_supported_speeds(shost) = FC_PORTSPEED_UNKNOWN;
fc_host_maxframe_size(shost) = -1;
memset(fc_host_hardware_version(shost), 0,
sizeof(fc_host_hardware_version(shost)));
memset(fc_host_firmware_version(shost), 0,
sizeof(fc_host_firmware_version(shost)));
memset(fc_host_serial_number(shost), 0,
sizeof(fc_host_serial_number(shost)));
memset(fc_host_opt_rom_version(shost), 0,
sizeof(fc_host_opt_rom_version(shost)));
memset(fc_host_driver_version(shost), 0,
sizeof(fc_host_driver_version(shost)));
fc_host_port_id(shost) = -1;
fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
......@@ -536,6 +546,11 @@ fc_private_host_rd_attr_cast(node_name, "0x%llx\n", 20, unsigned long long);
fc_private_host_rd_attr_cast(port_name, "0x%llx\n", 20, unsigned long long);
fc_private_host_rd_attr(symbolic_name, "%s\n", (FC_SYMBOLIC_NAME_SIZE +1));
fc_private_host_rd_attr(maxframe_size, "%u bytes\n", 20);
fc_private_host_rd_attr(hardware_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
fc_private_host_rd_attr(firmware_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
fc_private_host_rd_attr(serial_number, "%s\n", (FC_SERIAL_NUMBER_SIZE +1));
fc_private_host_rd_attr(opt_rom_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
fc_private_host_rd_attr(driver_version, "%s\n", (FC_VERSION_STRING_SIZE +1));
/* Dynamic Host Attributes */
......@@ -772,6 +787,11 @@ fc_attach_transport(struct fc_function_template *ft)
SETUP_HOST_ATTRIBUTE_RD(symbolic_name);
SETUP_HOST_ATTRIBUTE_RD(supported_speeds);
SETUP_HOST_ATTRIBUTE_RD(maxframe_size);
SETUP_HOST_ATTRIBUTE_RD(hardware_version);
SETUP_HOST_ATTRIBUTE_RD(firmware_version);
SETUP_HOST_ATTRIBUTE_RD(serial_number);
SETUP_HOST_ATTRIBUTE_RD(opt_rom_version);
SETUP_HOST_ATTRIBUTE_RD(driver_version);
SETUP_HOST_ATTRIBUTE_RD(port_id);
SETUP_HOST_ATTRIBUTE_RD(port_type);
......@@ -808,10 +828,9 @@ EXPORT_SYMBOL(fc_release_transport);
* @dev: scsi device
* @data: unused
**/
static int fc_device_block(struct device *dev, void *data)
static void fc_device_block(struct scsi_device *sdev, void *data)
{
scsi_internal_device_block(to_scsi_device(dev));
return 0;
scsi_internal_device_block(sdev);
}
/**
......@@ -819,10 +838,9 @@ static int fc_device_block(struct device *dev, void *data)
* @dev: scsi device
* @data: unused
**/
static int fc_device_unblock(struct device *dev, void *data)
static void fc_device_unblock(struct scsi_device *sdev, void *data)
{
scsi_internal_device_unblock(to_scsi_device(dev));
return 0;
scsi_internal_device_unblock(sdev);
}
/**
......@@ -842,7 +860,7 @@ static void fc_timeout_blocked_tgt(void *data)
* unblock this device, then IO errors will probably
* result if the host still isn't ready.
*/
device_for_each_child(&starget->dev, NULL, fc_device_unblock);
starget_for_each_device(starget, NULL, fc_device_unblock);
}
/**
......@@ -870,7 +888,7 @@ fc_target_block(struct scsi_target *starget)
if (timeout < 0 || timeout > SCSI_DEVICE_BLOCK_MAX_TIMEOUT)
return -EINVAL;
device_for_each_child(&starget->dev, NULL, fc_device_block);
starget_for_each_device(starget, NULL, fc_device_block);
/* The scsi lld blocks this target for the timeout period only. */
schedule_delayed_work(work, timeout * HZ);
......@@ -901,7 +919,7 @@ fc_target_unblock(struct scsi_target *starget)
if (cancel_delayed_work(&fc_starget_dev_loss_work(starget)))
flush_scheduled_work();
device_for_each_child(&starget->dev, NULL, fc_device_unblock);
starget_for_each_device(starget, NULL, fc_device_unblock);
}
EXPORT_SYMBOL(fc_target_unblock);
......
......@@ -31,6 +31,7 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_request.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
......@@ -378,10 +379,16 @@ static CLASS_DEVICE_ATTR(signalling, S_IRUGO | S_IWUSR,
#define DV_RETRIES 3 /* should only need at most
* two cc/ua clears */
enum spi_compare_returns {
SPI_COMPARE_SUCCESS,
SPI_COMPARE_FAILURE,
SPI_COMPARE_SKIP_TEST,
};
/* This is for read/write Domain Validation: If the device supports
* an echo buffer, we do read/write tests to it */
static int
static enum spi_compare_returns
spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
u8 *ptr, const int retries)
{
......@@ -438,9 +445,23 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
scsi_wait_req(sreq, spi_write_buffer, buffer, len,
DV_TIMEOUT, DV_RETRIES);
if(sreq->sr_result || !scsi_device_online(sdev)) {
struct scsi_sense_hdr sshdr;
scsi_device_set_state(sdev, SDEV_QUIESCE);
if (scsi_request_normalize_sense(sreq, &sshdr)
&& sshdr.sense_key == ILLEGAL_REQUEST
/* INVALID FIELD IN CDB */
&& sshdr.asc == 0x24 && sshdr.ascq == 0x00)
/* This would mean that the drive lied
* to us about supporting an echo
* buffer (unfortunately some Western
* Digital drives do precisely this)
*/
return SPI_COMPARE_SKIP_TEST;
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result);
return 0;
return SPI_COMPARE_FAILURE;
}
memset(ptr, 0, len);
......@@ -451,14 +472,14 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
scsi_device_set_state(sdev, SDEV_QUIESCE);
if (memcmp(buffer, ptr, len) != 0)
return 0;
return SPI_COMPARE_FAILURE;
}
return 1;
return SPI_COMPARE_SUCCESS;
}
/* This is for the simplest form of Domain Validation: a read test
* on the inquiry data from the device */
static int
static enum spi_compare_returns
spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
u8 *ptr, const int retries)
{
......@@ -480,7 +501,7 @@ spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
if(sreq->sr_result || !scsi_device_online(sdev)) {
scsi_device_set_state(sdev, SDEV_QUIESCE);
return 0;
return SPI_COMPARE_FAILURE;
}
/* If we don't have the inquiry data already, the
......@@ -493,24 +514,28 @@ spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer,
if (memcmp(buffer, ptr, len) != 0)
/* failure */
return 0;
return SPI_COMPARE_FAILURE;
}
return 1;
return SPI_COMPARE_SUCCESS;
}
static int
static enum spi_compare_returns
spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
int (*compare_fn)(struct scsi_request *, u8 *, u8 *, int))
enum spi_compare_returns
(*compare_fn)(struct scsi_request *, u8 *, u8 *, int))
{
struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
struct scsi_device *sdev = sreq->sr_device;
int period = 0, prevperiod = 0;
enum spi_compare_returns retval;
for (;;) {
int newperiod;
if (compare_fn(sreq, buffer, ptr, DV_LOOPS))
/* Successful DV */
retval = compare_fn(sreq, buffer, ptr, DV_LOOPS);
if (retval == SPI_COMPARE_SUCCESS
|| retval == SPI_COMPARE_SKIP_TEST)
break;
/* OK, retrain, fallback */
......@@ -527,13 +552,13 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
/* Total failure; set to async and return */
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n");
DV_SET(offset, 0);
return 0;
return SPI_COMPARE_FAILURE;
}
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation detected failure, dropping back\n");
DV_SET(period, period);
prevperiod = period;
}
return 1;
return retval;
}
static int
......@@ -599,7 +624,8 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
DV_SET(offset, 0);
DV_SET(width, 0);
if (!spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)) {
if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)
!= SPI_COMPARE_SUCCESS) {
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
/* FIXME: should probably offline the device here? */
return;
......@@ -609,9 +635,10 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
if (i->f->set_width && sdev->wdtr) {
i->f->set_width(sdev->sdev_target, 1);
if (!spi_dv_device_compare_inquiry(sreq, buffer,
if (spi_dv_device_compare_inquiry(sreq, buffer,
buffer + len,
DV_LOOPS)) {
DV_LOOPS)
!= SPI_COMPARE_SUCCESS) {
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Wide Transfers Fail\n");
i->f->set_width(sdev->sdev_target, 0);
}
......@@ -624,31 +651,39 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
if(!sdev->ppr && !sdev->sdtr)
return;
/* now set up to the maximum */
DV_SET(offset, 255);
DV_SET(period, 1);
if (!spi_dv_retrain(sreq, buffer, buffer + len,
spi_dv_device_compare_inquiry))
return;
/* OK, now we have our initial speed set by the read only inquiry
* test, now try an echo buffer test (if the device allows it) */
/* see if the device has an echo buffer. If it does we can
* do the SPI pattern write tests */
len = 0;
if (sdev->ppr)
len = spi_dv_device_get_echo_buffer(sreq, buffer);
retry:
/* now set up to the maximum */
DV_SET(offset, 255);
DV_SET(period, 1);
if (len == 0) {
SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n");
spi_dv_retrain(sreq, buffer, buffer + len,
spi_dv_device_compare_inquiry);
return;
}
if (len > SPI_MAX_ECHO_BUFFER_SIZE) {
SPI_PRINTK(sdev->sdev_target, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE);
len = SPI_MAX_ECHO_BUFFER_SIZE;
}
spi_dv_retrain(sreq, buffer, buffer + len,
spi_dv_device_echo_buffer);
if (spi_dv_retrain(sreq, buffer, buffer + len,
spi_dv_device_echo_buffer)
== SPI_COMPARE_SKIP_TEST) {
/* OK, the stupid drive can't do a write echo buffer
* test after all, fall back to the read tests */
len = 0;
goto retry;
}
}
......
......@@ -1082,9 +1082,12 @@ sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
" READ CAPACITY(16).\n", diskname);
longrc = 1;
goto repeat;
} else {
printk(KERN_ERR "%s: too big for kernel. Assuming maximum 2Tb\n", diskname);
}
printk(KERN_ERR "%s: too big for this kernel. Use a "
"kernel compiled with support for large block "
"devices.\n", diskname);
sdkp->capacity = 0;
goto got_data;
}
sdkp->capacity = 1 + (((sector_t)buffer[0] << 24) |
(buffer[1] << 16) |
......
......@@ -78,14 +78,6 @@
*/
/* #define SYM_CONF_IARB_SUPPORT */
/*
* Number of lists for the optimization of the IO timeout handling.
* Not used under FreeBSD and Linux.
*/
#ifndef SYM_CONF_TIMEOUT_ORDER_MAX
#define SYM_CONF_TIMEOUT_ORDER_MAX (8)
#endif
/*
* Only relevant if IARB support configured.
* - Max number of successive settings of IARB hints.
......
......@@ -40,29 +40,9 @@
#ifndef SYM_DEFS_H
#define SYM_DEFS_H
#define SYM_VERSION "2.1.18m"
#define SYM_VERSION "2.1.18n"
#define SYM_DRIVER_NAME "sym-" SYM_VERSION
/*
* PCI device identifier of SYMBIOS chips.
*/
#define PCI_ID_SYM53C810 PCI_DEVICE_ID_NCR_53C810
#define PCI_ID_SYM53C810AP PCI_DEVICE_ID_LSI_53C810AP
#define PCI_ID_SYM53C815 PCI_DEVICE_ID_NCR_53C815
#define PCI_ID_SYM53C820 PCI_DEVICE_ID_NCR_53C820
#define PCI_ID_SYM53C825 PCI_DEVICE_ID_NCR_53C825
#define PCI_ID_SYM53C860 PCI_DEVICE_ID_NCR_53C860
#define PCI_ID_SYM53C875 PCI_DEVICE_ID_NCR_53C875
#define PCI_ID_SYM53C875_2 PCI_DEVICE_ID_NCR_53C875J
#define PCI_ID_SYM53C885 PCI_DEVICE_ID_NCR_53C885
#define PCI_ID_SYM53C895 PCI_DEVICE_ID_NCR_53C895
#define PCI_ID_SYM53C896 PCI_DEVICE_ID_NCR_53C896
#define PCI_ID_SYM53C895A PCI_DEVICE_ID_LSI_53C895A
#define PCI_ID_SYM53C875A PCI_DEVICE_ID_LSI_53C875A
#define PCI_ID_LSI53C1010_33 PCI_DEVICE_ID_LSI_53C1010_33
#define PCI_ID_LSI53C1010_66 PCI_DEVICE_ID_LSI_53C1010_66
#define PCI_ID_LSI53C1510D PCI_DEVICE_ID_LSI_53C1510
/*
* SYM53C8XX device features descriptor.
*/
......@@ -764,27 +744,27 @@ struct sym_tblsel {
#define M_RESTORE_DP RESTORE_POINTERS
#define M_DISCONNECT DISCONNECT
#define M_ID_ERROR INITIATOR_ERROR
#define M_ABORT ABORT
#define M_ABORT ABORT_TASK_SET
#define M_REJECT MESSAGE_REJECT
#define M_NOOP NOP
#define M_PARITY MSG_PARITY_ERROR
#define M_LCOMPLETE LINKED_CMD_COMPLETE
#define M_FCOMPLETE LINKED_FLG_CMD_COMPLETE
#define M_RESET BUS_DEVICE_RESET
#define M_ABORT_TAG (0x0d)
#define M_CLEAR_QUEUE (0x0e)
#define M_RESET TARGET_RESET
#define M_ABORT_TAG ABORT_TASK
#define M_CLEAR_QUEUE CLEAR_TASK_SET
#define M_INIT_REC INITIATE_RECOVERY
#define M_REL_REC RELEASE_RECOVERY
#define M_TERMINATE (0x11)
#define M_SIMPLE_TAG SIMPLE_QUEUE_TAG
#define M_HEAD_TAG HEAD_OF_QUEUE_TAG
#define M_ORDERED_TAG ORDERED_QUEUE_TAG
#define M_IGN_RESIDUE (0x23)
#define M_IGN_RESIDUE IGNORE_WIDE_RESIDUE
#define M_X_MODIFY_DP EXTENDED_MODIFY_DATA_POINTER
#define M_X_SYNC_REQ EXTENDED_SDTR
#define M_X_WIDE_REQ EXTENDED_WDTR
#define M_X_PPR_REQ (0x04)
#define M_X_PPR_REQ EXTENDED_PPR
/*
* PPR protocol options
......
......@@ -223,13 +223,13 @@ sym_fw2_patch(struct sym_hcb *np)
* Remove a couple of work-arounds specific to C1010 if
* they are not desirable. See `sym_fw2.h' for more details.
*/
if (!(np->device_id == PCI_ID_LSI53C1010_66 &&
if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_66 &&
np->revision_id < 0x1 &&
np->pciclk_khz < 60000)) {
scripta0->datao_phase[0] = cpu_to_scr(SCR_NO_OP);
scripta0->datao_phase[1] = cpu_to_scr(0);
}
if (!(np->device_id == PCI_ID_LSI53C1010_33 &&
if (!(np->device_id == PCI_DEVICE_ID_LSI_53C1010_33 &&
/* np->revision_id < 0xff */ 1)) {
scripta0->sel_done[0] = cpu_to_scr(SCR_NO_OP);
scripta0->sel_done[1] = cpu_to_scr(0);
......
......@@ -55,6 +55,15 @@
#define NAME53C "sym53c"
#define NAME53C8XX "sym53c8xx"
/* SPARC just has to be different ... */
#ifdef __sparc__
#define IRQ_FMT "%s"
#define IRQ_PRM(x) __irq_itoa(x)
#else
#define IRQ_FMT "%d"
#define IRQ_PRM(x) (x)
#endif
struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP;
unsigned int sym_debug_flags = 0;
......@@ -147,7 +156,7 @@ pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
}
/* This lock protects only the memory allocation/free. */
spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
static spinlock_t sym53c8xx_lock = SPIN_LOCK_UNLOCKED;
static struct scsi_transport_template *sym2_transport_template = NULL;
......@@ -285,7 +294,7 @@ void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb)
ccb->scsi_done(ccb);
}
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 *ccb, int cam_status)
{
sym_set_cam_status(ccb, cam_status);
sym_xpt_done(np, ccb);
......@@ -379,7 +388,7 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
/*
* Bounce back the sense data to user.
*/
bzero(&csio->sense_buffer, sizeof(csio->sense_buffer));
memset(&csio->sense_buffer, 0, sizeof(csio->sense_buffer));
memcpy(csio->sense_buffer, cp->sns_bbuf,
min(sizeof(csio->sense_buffer),
(size_t)SYM_SNS_BBUF_LEN));
......@@ -513,7 +522,7 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *ccb)
}
/*
* Retreive the target descriptor.
* Retrieve the target descriptor.
*/
tp = &np->target[ccb->device->id];
......@@ -1277,7 +1286,7 @@ static int sym_user_command(struct sym_hcb *np, char *buffer, int length)
int arg_len;
u_long target;
bzero(uc, sizeof(*uc));
memset(uc, 0, sizeof(*uc));
if (len > 0 && ptr[len-1] == '\n')
--len;
......@@ -1467,18 +1476,8 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "
"revision id 0x%x\n",
np->s.chip_name, np->device_id, np->revision_id);
copy_info(&info, "At PCI address %s, "
#ifdef __sparc__
"IRQ %s\n",
#else
"IRQ %d\n",
#endif
pci_name(np->s.device),
#ifdef __sparc__
__irq_itoa(np->s.irq));
#else
(int) np->s.irq);
#endif
copy_info(&info, "At PCI address %s, IRQ " IRQ_FMT "\n",
pci_name(np->s.device), IRQ_PRM(np->s.irq));
copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n",
(int) (np->minsync_dt ? np->minsync_dt : np->minsync),
np->maxwide ? "Wide" : "Narrow",
......@@ -1558,32 +1557,23 @@ static void sym_free_resources(struct sym_hcb *np)
*/
static int sym_setup_bus_dma_mask(struct sym_hcb *np)
{
#if SYM_CONF_DMA_ADDRESSING_MODE == 0
if (pci_set_dma_mask(np->s.device, 0xffffffffUL))
goto out_err32;
#else
#if SYM_CONF_DMA_ADDRESSING_MODE > 0
#if SYM_CONF_DMA_ADDRESSING_MODE == 1
#define PciDmaMask 0xffffffffffULL
#define DMA_DAC_MASK 0x000000ffffffffffULL /* 40-bit */
#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
#define PciDmaMask 0xffffffffffffffffULL
#define DMA_DAC_MASK DMA_64BIT_MASK
#endif
if (np->features & FE_DAC) {
if (!pci_set_dma_mask(np->s.device, PciDmaMask)) {
np->use_dac = 1;
printf_info("%s: using 64 bit DMA addressing\n",
sym_name(np));
} else {
if (pci_set_dma_mask(np->s.device, 0xffffffffUL))
goto out_err32;
}
if ((np->features & FE_DAC) &&
!pci_set_dma_mask(np->s.device, DMA_DAC_MASK)) {
np->use_dac = 1;
return 0;
}
#undef PciDmaMask
#endif
return 0;
out_err32:
printf_warning("%s: 32 BIT DMA ADDRESSING NOT SUPPORTED\n",
sym_name(np));
if (!pci_set_dma_mask(np->s.device, DMA_32BIT_MASK))
return 0;
printf_warning("%s: No suitable DMA available\n", sym_name(np));
return -1;
}
......@@ -1606,19 +1596,9 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
struct sym_fw *fw;
printk(KERN_INFO
"sym%d: <%s> rev 0x%x at pci %s "
#ifdef __sparc__
"irq %s\n",
#else
"irq %d\n",
#endif
"sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n",
unit, dev->chip.name, dev->chip.revision_id,
pci_name(dev->pdev),
#ifdef __sparc__
__irq_itoa(dev->s.irq));
#else
dev->s.irq);
#endif
pci_name(dev->pdev), IRQ_PRM(dev->s.irq));
/*
* Get the firmware for this chip.
......@@ -1672,9 +1652,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
strlcpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name));
sprintf(np->s.inst_name, "sym%d", np->s.unit);
/*
* Ask/tell the system about DMA addressing.
*/
if (sym_setup_bus_dma_mask(np))
goto attach_failed;
......@@ -2010,7 +1987,7 @@ sym_init_device(struct pci_dev *pdev, struct sym_device *device)
* the preset SCSI ID (which may be zero) must be read in from
* a special configuration space register of the 875.
*/
void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
static void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
{
int slot;
u8 tmp;
......
......@@ -58,13 +58,6 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#ifndef bzero
#define bzero(d, n) memset((d), 0, (n))
#endif
/*
* General driver includes.
*/
#include "sym_conf.h"
#include "sym_defs.h"
#include "sym_misc.h"
......@@ -123,14 +116,6 @@
typedef struct sym_tcb *tcb_p;
typedef struct sym_lcb *lcb_p;
typedef struct sym_ccb *ccb_p;
typedef struct sym_hcb *hcb_p;
/*
* Define a reference to the O/S dependent IO request.
*/
typedef struct scsi_cmnd *cam_ccb_p; /* Generic */
typedef struct scsi_cmnd *cam_scsiio_p;/* SCSI I/O */
/*
* IO functions definition for big/little endian CPU support.
......@@ -525,7 +510,7 @@ sym_get_cam_status(struct scsi_cmnd *ccb)
/*
* Async handler for negotiations.
*/
void sym_xpt_async_nego_wide(hcb_p np, int target);
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) \
......@@ -534,14 +519,14 @@ void sym_xpt_async_nego_wide(hcb_p np, int target);
/*
* Build CAM result for a successful IO and for a failed IO.
*/
static __inline void sym_set_cam_result_ok(hcb_p np, ccb_p cp, int resid)
static __inline void sym_set_cam_result_ok(struct sym_hcb *np, ccb_p cp, int resid)
{
struct scsi_cmnd *cmd = cp->cam_ccb;
cmd->resid = resid;
cmd->result = (((DID_OK) << 16) + ((cp->ssss_status) & 0x7f));
}
void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid);
void sym_set_cam_result_error(struct sym_hcb *np, ccb_p cp, int resid);
/*
* Other O/S specific methods.
......@@ -549,13 +534,12 @@ void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid);
#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(hcb_p np, cam_ccb_p ccb);
void sym_xpt_done2(hcb_p np, cam_ccb_p ccb, int cam_status);
void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb);
void sym_print_addr (ccb_p cp);
void sym_xpt_async_bus_reset(hcb_p np);
void sym_xpt_async_sent_bdr(hcb_p np, int target);
int sym_setup_data_and_start (hcb_p np, cam_scsiio_p csio, ccb_p cp);
void sym_log_bus_error(hcb_p np);
void sym_sniff_inquiry(hcb_p np, struct scsi_cmnd *cmd, int resid);
void sym_xpt_async_bus_reset(struct sym_hcb *np);
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);
void sym_log_bus_error(struct sym_hcb *np);
void sym_sniff_inquiry(struct sym_hcb *np, struct scsi_cmnd *cmd, int resid);
#endif /* SYM_GLUE_H */
This diff is collapsed.
......@@ -749,7 +749,7 @@ struct sym_ccb {
/*
* Pointer to CAM ccb and related stuff.
*/
cam_ccb_p cam_ccb; /* CAM scsiio ccb */
struct scsi_cmnd *cam_ccb; /* CAM scsiio ccb */
u8 cdb_buf[16]; /* Copy of CDB */
u8 *sns_bbuf; /* Bounce buffer for sense data */
#ifndef SYM_SNS_BBUF_LEN
......@@ -796,10 +796,6 @@ struct sym_ccb {
/*
* Other fields.
*/
#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
SYM_QUEHEAD tmo_linkq; /* Optional timeout handling */
u_int tmo_clock; /* (link and dealine value) */
#endif
u32 ccb_ba; /* BUS address of this CCB */
u_short tag; /* Tag for this transfer */
/* NO_TAG means no tag */
......@@ -946,8 +942,8 @@ struct sym_hcb {
struct sym_fwa_ba fwa_bas; /* Useful SCRIPTA bus addresses */
struct sym_fwb_ba fwb_bas; /* Useful SCRIPTB bus addresses */
struct sym_fwz_ba fwz_bas; /* Useful SCRIPTZ bus addresses */
void (*fw_setup)(hcb_p np, struct sym_fw *fw);
void (*fw_patch)(hcb_p np);
void (*fw_setup)(struct sym_hcb *np, struct sym_fw *fw);
void (*fw_patch)(struct sym_hcb *np);
char *fw_name;
/*
......@@ -1025,15 +1021,6 @@ struct sym_hcb {
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
SYM_QUEHEAD dummy_ccbq;
#endif
/*
* Optional handling of IO timeouts.
*/
#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
SYM_QUEHEAD tmo0_ccbq;
SYM_QUEHEAD *tmo_ccbq; /* [2*SYM_TIMEOUT_ORDER_MAX] */
u_int tmo_clock;
u_int tmo_actq;
#endif
/*
* IMMEDIATE ARBITRATION (IARB) control.
......@@ -1082,54 +1069,39 @@ struct sym_hcb {
* FIRMWARES (sym_fw.c)
*/
struct sym_fw * sym_find_firmware(struct sym_pci_chip *chip);
void sym_fw_bind_script (hcb_p 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.
*/
char *sym_driver_name(void);
void sym_print_xerr(ccb_p cp, int x_status);
int sym_reset_scsi_bus(hcb_p np, int enab_int);
int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int);
struct sym_pci_chip *
sym_lookup_pci_chip_table (u_short device_id, u_char revision);
void sym_put_start_queue(hcb_p np, ccb_p cp);
void sym_put_start_queue(struct sym_hcb *np, ccb_p cp);
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn);
void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn);
#endif
void sym_start_up (hcb_p np, int reason);
void sym_interrupt (hcb_p np);
void sym_flush_comp_queue(hcb_p np, int cam_status);
int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task);
ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order);
void sym_free_ccb (hcb_p np, ccb_p cp);
lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln);
int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp);
int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out);
int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
int sym_reset_scsi_target(hcb_p np, int target);
void sym_hcb_free(hcb_p np);
int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram);
/*
* Optionnaly, the driver may handle IO timeouts.
*/
#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks);
static void __inline sym_untimeout_ccb(hcb_p np, ccb_p cp)
{
sym_remque(&cp->tmo_linkq);
sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
}
void sym_clock(hcb_p np);
#endif /* SYM_OPT_HANDLE_IO_TIMEOUT */
void sym_start_up (struct sym_hcb *np, int reason);
void sym_interrupt (struct sym_hcb *np);
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);
void sym_free_ccb (struct sym_hcb *np, ccb_p cp);
lcb_p 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_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);
void sym_hcb_free(struct sym_hcb *np);
int sym_hcb_attach(struct sym_hcb *np, 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(hcb_p np, int target);
void sym_announce_transfer_rate(struct sym_hcb *np, int target);
#endif
/*
......@@ -1153,9 +1125,9 @@ do { \
(data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len); \
} while (0)
#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
int sym_lookup_dmap(hcb_p np, u32 h, int s);
int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s);
static __inline void
sym_build_sge(hcb_p np, struct sym_tblmove *data, u64 badd, int len)
sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len)
{
u32 h = (badd>>32);
int s = (h&SYM_DMAP_MASK);
......
......@@ -170,7 +170,7 @@ static void *__sym_calloc2(m_pool_p mp, int size, char *name, int uflags)
}
if (p)
bzero(p, size);
memset(p, 0, size);
else if (uflags & SYM_MEM_WARN)
printf ("__sym_calloc2: failed to allocate %s[%d]\n", name, size);
return p;
......
......@@ -37,109 +37,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef __FreeBSD__
#include <dev/sym/sym_glue.h>
#else
#include "sym_glue.h"
#endif
#ifdef SYM_OPT_HANDLE_IO_TIMEOUT
/*
* Optional CCB timeout handling.
*
* This code is useful for O/Ses that allow or expect
* SIMs (low-level drivers) to handle SCSI IO timeouts.
* It uses a power-of-two based algorithm of my own:)
* that avoids scanning of lists, provided that:
*
* - The IO does complete in less than half the associated
* timeout value.
* - The greatest delay between the queuing of the IO and
* its completion is less than
* (1<<(SYM_CONF_TIMEOUT_ORDER_MAX-1))/2 ticks.
*
* For example, if tick is 1 second and the max order is 8,
* any IO that is completed within less than 64 seconds will
* just be put into some list at queuing and be removed
* at completion without any additionnal overhead.
*/
/*
* Set a timeout condition on a CCB.
*/
void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks)
{
sym_remque(&cp->tmo_linkq);
cp->tmo_clock = np->tmo_clock + ticks;
if (!ticks) {
sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
}
else {
int i = SYM_CONF_TIMEOUT_ORDER_MAX - 1;
while (i > 0) {
if (ticks >= (1<<(i+1)))
break;
--i;
}
if (!(np->tmo_actq & (1<<i)))
i += SYM_CONF_TIMEOUT_ORDER_MAX;
sym_insque_head(&cp->tmo_linkq, &np->tmo_ccbq[i]);
}
}
/*
* Walk a list of CCB and handle timeout conditions.
* Should never be called in normal situations.
*/
static void sym_walk_ccb_tmo_list(hcb_p np, SYM_QUEHEAD *tmoq)
{
SYM_QUEHEAD qtmp, *qp;
ccb_p cp;
sym_que_move(tmoq, &qtmp);
while ((qp = sym_remque_head(&qtmp)) != 0) {
sym_insque_head(qp, &np->tmo0_ccbq);
cp = sym_que_entry(qp, struct sym_ccb, tmo_linkq);
if (cp->tmo_clock != np->tmo_clock &&
cp->tmo_clock + 1 != np->tmo_clock)
sym_timeout_ccb(np, cp, cp->tmo_clock - np->tmo_clock);
else
sym_abort_ccb(np, cp, 1);
}
}
/*
* Our clock handler called from the O/S specific side.
*/
void sym_clock(hcb_p np)
{
int i, j;
u_int tmp;
tmp = np->tmo_clock;
tmp ^= (++np->tmo_clock);
for (i = 0; i < SYM_CONF_TIMEOUT_ORDER_MAX; i++, tmp >>= 1) {
if (!(tmp & 1))
continue;
j = i;
if (np->tmo_actq & (1<<i))
j += SYM_CONF_TIMEOUT_ORDER_MAX;
if (!sym_que_empty(&np->tmo_ccbq[j])) {
sym_walk_ccb_tmo_list(np, &np->tmo_ccbq[j]);
}
np->tmo_actq ^= (1<<i);
}
}
#endif /* SYM_OPT_HANDLE_IO_TIMEOUT */
#ifdef SYM_OPT_ANNOUNCE_TRANSFER_RATE
/*
* Announce transfer rate if anything changed since last announcement.
*/
void sym_announce_transfer_rate(hcb_p np, int target)
void sym_announce_transfer_rate(struct sym_hcb *np, int target)
{
tcb_p tp = &np->target[target];
......
......@@ -68,6 +68,21 @@ void sym_nvram_setup_host(struct sym_hcb *np, struct sym_nvram *nvram)
case SYM_TEKRAM_NVRAM:
np->myaddr = nvram->data.Tekram.host_id & 0x0f;
break;
#ifdef CONFIG_PARISC
case SYM_PARISC_PDC:
if (nvram->data.parisc.host_id != -1)
np->myaddr = nvram->data.parisc.host_id;
if (nvram->data.parisc.factor != -1)
np->minsync = nvram->data.parisc.factor;
if (nvram->data.parisc.width != -1)
np->maxwide = nvram->data.parisc.width;
switch (nvram->data.parisc.mode) {
case 0: np->scsi_mode = SMODE_SE; break;
case 1: np->scsi_mode = SMODE_HVD; break;
case 2: np->scsi_mode = SMODE_LVD; break;
default: break;
}
#endif
default:
break;
}
......@@ -702,6 +717,28 @@ static int sym_read_Tekram_nvram (struct sym_device *np, Tekram_nvram *nvram)
return 0;
}
#ifdef CONFIG_PARISC
/*
* Host firmware (PDC) keeps a table for altering SCSI capabilities.
* Many newer machines export one channel of 53c896 chip as SE, 50-pin HD.
* Also used for Multi-initiator SCSI clusters to set the SCSI Initiator ID.
*/
static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *pdc)
{
struct hardware_path hwpath;
get_pci_node_path(np->pdev, &hwpath);
if (!pdc_get_initiator(&hwpath, pdc))
return 0;
return SYM_PARISC_PDC;
}
#else
static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *x)
{
return 0;
}
#endif
/*
* Try reading Symbios or Tekram NVRAM
*/
......@@ -714,7 +751,7 @@ int sym_read_nvram(struct sym_device *np, struct sym_nvram *nvp)
nvp->type = SYM_TEKRAM_NVRAM;
sym_display_Tekram_nvram(np, &nvp->data.Tekram);
} else {
nvp->type = 0;
nvp->type = sym_read_parisc_pdc(np, &nvp->data.parisc);
}
return nvp->type;
}
......@@ -171,6 +171,10 @@ struct Tekram_nvram {
typedef struct Tekram_nvram Tekram_nvram;
typedef struct Tekram_target Tekram_target;
#ifndef CONFIG_PARISC
struct pdc_initiator { int dummy; };
#endif
/*
* Union of supported NVRAM formats.
*/
......@@ -178,10 +182,12 @@ struct sym_nvram {
int type;
#define SYM_SYMBIOS_NVRAM (1)
#define SYM_TEKRAM_NVRAM (2)
#define SYM_PARISC_PDC (3)
#if SYM_CONF_NVRAM_SUPPORT
union {
Symbios_nvram Symbios;
Tekram_nvram Tekram;
struct pdc_initiator parisc;
} data;
#endif
};
......
......@@ -505,8 +505,6 @@ static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd)
#define unmap_scsi_data(np, cmd) __unmap_scsi_data(np->dev, cmd)
#define map_scsi_single_data(np, cmd) __map_scsi_single_data(np->dev, cmd)
#define map_scsi_sg_data(np, cmd) __map_scsi_sg_data(np->dev, cmd)
#define sync_scsi_data_for_cpu(np, cmd) __sync_scsi_data_for_cpu(np->dev, cmd)
#define sync_scsi_data_for_device(np, cmd) __sync_scsi_data_for_device(np->dev, cmd)
/*==========================================================
**
......
......@@ -87,7 +87,7 @@ zalon_probe(struct parisc_device *dev)
{
struct gsc_irq gsc_irq;
u32 zalon_vers;
int irq, error = -ENODEV;
int error = -ENODEV;
unsigned long zalon = dev->hpa;
unsigned long io_port = zalon + GSC_SCSI_ZALON_OFFSET;
static int unit = 0;
......@@ -107,10 +107,10 @@ zalon_probe(struct parisc_device *dev)
/* Setup the interrupts first.
** Later on request_irq() will register the handler.
*/
irq = gsc_alloc_irq(&gsc_irq);
dev->irq = gsc_alloc_irq(&gsc_irq);
printk("%s: Zalon vers field is 0x%x, IRQ %d\n", __FUNCTION__,
zalon_vers, irq);
zalon_vers, dev->irq);
__raw_writel(gsc_irq.txn_addr | gsc_irq.txn_data, dev->hpa + IO_MODULE_EIM);
......@@ -130,16 +130,16 @@ zalon_probe(struct parisc_device *dev)
device.dev = &dev->dev;
device.slot.base = (u_long)io_port;
device.slot.base_c = (u_long)io_port;
device.slot.irq = irq;
device.slot.irq = dev->irq;
device.differential = 2;
host = ncr_attach(&zalon7xx_template, unit, &device);
if (!host)
goto fail;
if (request_irq(irq, ncr53c8xx_intr, SA_SHIRQ, dev->dev.bus_id, host)) {
if (request_irq(dev->irq, ncr53c8xx_intr, SA_SHIRQ, "zalon", host)) {
printk(KERN_ERR "%s: irq problem with %d, detaching\n ",
dev->dev.bus_id, irq);
dev->dev.bus_id, dev->irq);
goto fail;
}
......@@ -155,7 +155,7 @@ zalon_probe(struct parisc_device *dev)
return 0;
fail_free_irq:
free_irq(irq, host);
free_irq(dev->irq, host);
fail:
ncr53c8xx_release(host);
return error;
......@@ -171,18 +171,16 @@ MODULE_DEVICE_TABLE(parisc, zalon_tbl);
static int __exit zalon_remove(struct parisc_device *dev)
{
struct Scsi_Host *host = dev_get_drvdata(&dev->dev);
int irq = host->irq;
scsi_remove_host(host);
ncr53c8xx_release(host);
free_irq(irq, host);
free_irq(dev->irq, host);
return 0;
}
static struct parisc_driver zalon_driver = {
.name = "GSC SCSI (Zalon)",
.name = "zalon",
.id_table = zalon_tbl,
.probe = zalon_probe,
.remove = __devexit_p(zalon_remove),
......@@ -201,6 +199,7 @@ static int __init zalon7xx_init(void)
static void __exit zalon7xx_exit(void)
{
unregister_parisc_driver(&zalon_driver);
ncr53c8xx_exit();
}
module_init(zalon7xx_init);
......
......@@ -8,6 +8,9 @@ extern void scsi_print_command(struct scsi_cmnd *);
extern void __scsi_print_command(unsigned char *);
extern void scsi_print_sense(const char *, struct scsi_cmnd *);
extern void scsi_print_req_sense(const char *, struct scsi_request *);
extern void __scsi_print_sense(const char *name,
const unsigned char *sense_buffer,
int sense_len);
extern void scsi_print_driverbyte(int);
extern void scsi_print_hostbyte(int);
extern void scsi_print_status(unsigned char);
......
......@@ -172,6 +172,8 @@ extern struct scsi_device *scsi_device_lookup(struct Scsi_Host *,
uint, uint, uint);
extern struct scsi_device *__scsi_device_lookup(struct Scsi_Host *,
uint, uint, uint);
extern void starget_for_each_device(struct scsi_target *, void *,
void (*fn)(struct scsi_device *, void *));
/* only exposed to implement shost_for_each_device */
extern struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *,
......
......@@ -185,6 +185,8 @@ struct fc_host_statistics {
#define FC_FC4_LIST_SIZE 32
#define FC_SYMBOLIC_NAME_SIZE 256
#define FC_VERSION_STRING_SIZE 64
#define FC_SERIAL_NUMBER_SIZE 80
struct fc_host_attrs {
/* Fixed Attributes */
......@@ -195,6 +197,11 @@ struct fc_host_attrs {
char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
u32 supported_speeds;
u32 maxframe_size;
char hardware_version[FC_VERSION_STRING_SIZE];
char firmware_version[FC_VERSION_STRING_SIZE];
char serial_number[FC_SERIAL_NUMBER_SIZE];
char opt_rom_version[FC_VERSION_STRING_SIZE];
char driver_version[FC_VERSION_STRING_SIZE];
/* Dynamic Attributes */
u32 port_id;
......@@ -226,6 +233,16 @@ struct fc_host_attrs {
(((struct fc_host_attrs *)(x)->shost_data)->supported_speeds)
#define fc_host_maxframe_size(x) \
(((struct fc_host_attrs *)(x)->shost_data)->maxframe_size)
#define fc_host_hardware_version(x) \
(((struct fc_host_attrs *)(x)->shost_data)->hardware_version)
#define fc_host_firmware_version(x) \
(((struct fc_host_attrs *)(x)->shost_data)->firmware_version)
#define fc_host_serial_number(x) \
(((struct fc_host_attrs *)(x)->shost_data)->serial_number)
#define fc_host_opt_rom_version(x) \
(((struct fc_host_attrs *)(x)->shost_data)->opt_rom_version)
#define fc_host_driver_version(x) \
(((struct fc_host_attrs *)(x)->shost_data)->driver_version)
#define fc_host_port_id(x) \
(((struct fc_host_attrs *)(x)->shost_data)->port_id)
#define fc_host_port_type(x) \
......@@ -285,6 +302,11 @@ struct fc_function_template {
unsigned long show_host_symbolic_name:1;
unsigned long show_host_supported_speeds:1;
unsigned long show_host_maxframe_size:1;
unsigned long show_host_hardware_version:1;
unsigned long show_host_firmware_version:1;
unsigned long show_host_serial_number:1;
unsigned long show_host_opt_rom_version:1;
unsigned long show_host_driver_version:1;
/* host dynamic attributes */
unsigned long show_host_port_id:1;
unsigned long show_host_port_type:1;
......
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