Commit 7934d2d8 authored by James Bottomley's avatar James Bottomley

Merge dj/hch fixes

parents 6bbb049e 6a50969a
......@@ -1325,9 +1325,9 @@ config SCSI_QLOGIC_FC_FIRMWARE
bool "Include loadable firmware in driver"
depends on SCSI_QLOGIC_FC
help
Say Y to include ISP2100 Fabric Initiator/Target Firmware, with
Say Y to include ISP2X00 Fabric Initiator/Target Firmware, with
expanded LUN addressing and FcTape (FCP-2) support, in the
Qlogic QLA 1280 driver. This is required on some platforms.
qlogicfc driver. This is required on some platforms.
config SCSI_QLOGIC_1280
tristate "Qlogic QLA 1280 SCSI support"
......
......@@ -120,13 +120,11 @@ obj-$(CONFIG_BLK_DEV_SD) += sd_mod.o
obj-$(CONFIG_BLK_DEV_SR) += sr_mod.o
obj-$(CONFIG_CHR_DEV_SG) += sg.o
scsi_mod-objs := scsi.o hosts.o scsi_ioctl.o constants.o scsicam.o \
scsi_error.o scsi_lib.o scsi_scan.o scsi_syms.o \
scsi_sysfs.o
ifdef CONFIG_PROC_FS
scsi_mod-objs += scsi_proc.o
endif
scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \
scsicam.o scsi_error.o scsi_lib.o \
scsi_scan.o scsi_syms.o scsi_sysfs.o
scsi_mod-$(CONFIG_PROC_FS) += scsi_proc.o
scsi_mod-$(CONFIG_X86_PC9800) += scsi_pc98.o
sd_mod-objs := sd.o
sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o
......
......@@ -60,7 +60,7 @@
#define AAC_DRIVERNAME "aacraid"
MODULE_AUTHOR("Red Hat Inc and Adaptec");
MODULE_DESCRIPTION("Supports Dell PERC2, 2/Si, 3/Si, 3/Di, Adaptec 2120S, 2200S, 5400S, and HP NetRAID-4M devices. http://domsch.com/linux/ or http://linux.adaptec.com");
MODULE_DESCRIPTION("Supports Dell PERC2, 2/Si, 3/Si, 3/Di, PERC 320/DC, Adaptec 2120S, 2200S, 5400S, and HP NetRAID-4M devices. http://domsch.com/linux/ or http://linux.adaptec.com");
MODULE_LICENSE("GPL");
MODULE_PARM(nondasd, "i");
MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");
......@@ -96,6 +96,7 @@ static struct aac_driver_ident aac_drivers[] = {
{ 0x9005, 0x0285, 0x9005, 0x0286, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1 }, /* Adaptec 2120S (Crusader)*/
{ 0x9005, 0x0285, 0x9005, 0x0285, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2 }, /* Adaptec 2200S (Vulcan)*/
{ 0x9005, 0x0285, 0x9005, 0x0287, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2 }, /* Adaptec 2200S (Vulcan-2m)*/
{ 0x9005, 0x0285, 0x1028, 0x0287, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* Dell PERC 320/DC */
{ 0x1011, 0x0046, 0x9005, 0x0365, aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4 }, /* Adaptec 5400S (Mustang)*/
{ 0x1011, 0x0046, 0x9005, 0x0364, aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4 }, /* Adaptec 5400S (Mustang)*/
{ 0x1011, 0x0046, 0x9005, 0x1364, aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4 }, /* Dell PERC2 "Quad Channel" */
......@@ -110,10 +111,10 @@ static int aac_cfg_open(struct inode * inode, struct file * file);
static int aac_cfg_release(struct inode * inode,struct file * file);
static struct file_operations aac_cfg_fops = {
owner: THIS_MODULE,
ioctl: aac_cfg_ioctl,
open: aac_cfg_open,
release: aac_cfg_release
.owner = THIS_MODULE,
.ioctl = aac_cfg_ioctl,
.open = aac_cfg_open,
.release = aac_cfg_release
};
static int aac_detect(Scsi_Host_Template *);
......
......@@ -2663,7 +2663,7 @@ static void datai_run(struct Scsi_Host *shpnt)
* STCNT to trigger ENSWRAP interrupt, instead of
* polling for DFIFOFULL
*/
the_time=jiffies + 10*HZ;
the_time=jiffies + 100*HZ;
while(TESTLO(DMASTAT, DFIFOFULL|INTSTAT) && time_before(jiffies,the_time))
barrier();
......@@ -2676,7 +2676,7 @@ static void datai_run(struct Scsi_Host *shpnt)
if(TESTHI(DMASTAT, DFIFOFULL)) {
fifodata = 128;
} else {
the_time=jiffies + 10*HZ;
the_time=jiffies + 100*HZ;
while(TESTLO(SSTAT2, SEMPTY) && time_before(jiffies,the_time))
barrier();
......@@ -2832,7 +2832,7 @@ static void datao_run(struct Scsi_Host *shpnt)
CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
}
the_time=jiffies + 10*HZ;
the_time=jiffies + 100*HZ;
while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT) && time_before(jiffies,the_time))
barrier();
......
......@@ -86,7 +86,7 @@ static dpt_sig_S DPTI_sig = {
#elif defined(__alpha__)
PROC_ALPHA ,
#else
(-1),
(-1),(-1)
#endif
FT_HBADRVR, 0, OEM_DPT, OS_LINUX, CAP_OVERLAP, DEV_ALL,
ADF_ALL_SC5, 0, 0, DPT_VERSION, DPT_REVISION, DPT_SUBREVISION,
......@@ -1135,7 +1135,8 @@ static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout)
// to support async LCT get
wait_data->next = adpt_post_wait_queue;
adpt_post_wait_queue = wait_data;
adpt_post_wait_id = (++adpt_post_wait_id & 0x7fff);
adpt_post_wait_id++;
adpt_post_wait_id &= 0x7fff;
wait_data->id = adpt_post_wait_id;
spin_unlock_irqrestore(&adpt_post_wait_lock, flags);
......
......@@ -725,13 +725,13 @@ static int fdomain_isa_detect( int *irq, int *iobase )
switch (Quantum) {
case 2: /* ISA_200S */
case 3: /* ISA_250MG */
base = readb(bios_base + 0x1fa2) + (readb(bios_base + 0x1fa3) << 8);
base = isa_readb(bios_base + 0x1fa2) + (isa_readb(bios_base + 0x1fa3) << 8);
break;
case 4: /* ISA_200S (another one) */
base = readb(bios_base + 0x1fa3) + (readb(bios_base + 0x1fa4) << 8);
base = isa_readb(bios_base + 0x1fa3) + (isa_readb(bios_base + 0x1fa4) << 8);
break;
default:
base = readb(bios_base + 0x1fcc) + (readb(bios_base + 0x1fcd) << 8);
base = isa_readb(bios_base + 0x1fcc) + (isa_readb(bios_base + 0x1fcd) << 8);
break;
}
......@@ -1777,7 +1777,7 @@ static int fdomain_16x0_biosparam(struct scsi_device *sdev,
offset = bios_base + 0x1f31 + drive * 25;
break;
}
memcpy_fromio( &i, offset, sizeof( struct drive_info ) );
isa_memcpy_fromio( &i, offset, sizeof( struct drive_info ) );
info_array[0] = i.heads;
info_array[1] = i.sectors;
info_array[2] = i.cylinders;
......
......@@ -270,21 +270,6 @@ int scsi_remove_host(struct Scsi_Host *shost)
if (scsi_check_device_busy(sdev))
return 1;
/*
* Next we detach the high level drivers from the Scsi_Device
* structures
*/
list_for_each_entry(sdev, &shost->my_devices, siblings) {
scsi_detach_device(sdev);
/* If something still attached, punt */
if (sdev->attached) {
printk(KERN_ERR "Attached usage count = %d\n",
sdev->attached);
return 1;
}
}
scsi_forget_host(shost);
return 0;
}
......
......@@ -2,7 +2,7 @@
A driver for Future Domain-compatible PCMCIA SCSI cards
fdomain_cs.c 1.43 2000/06/12 21:27:25
fdomain_cs.c 1.47 2001/10/13 00:08:52
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
......@@ -19,8 +19,8 @@
are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
Alternatively, the contents of this file may be used under the
terms of the GNU General Public License version 2 (the "GPL"), in which
case the provisions of the GPL are applicable instead of the
terms of the GNU General Public License version 2 (the "GPL"), in
which case the provisions of the GPL are applicable instead of the
above. If you wish to allow the use of your version of this file
only under the terms of the GPL and not to allow others to use
your version of this file under the MPL, indicate your decision
......@@ -53,27 +53,30 @@
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#ifdef PCMCIA_DEBUG
static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
"fdomain_cs.c 1.43 2000/06/12 21:27:25 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
/*====================================================================*/
/* Parameters that can be set with 'insmod' */
/* Module parameters */
MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver");
MODULE_LICENSE("Dual MPL/GPL");
#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
/* Bit map of interrupts to choose from */
static u_int irq_mask = 0xdeb8;
INT_MODULE_PARM(irq_mask, 0xdeb8);
static int irq_list[4] = { -1 };
MODULE_PARM(irq_mask, "i");
MODULE_PARM(irq_list, "1-4i");
#ifdef PCMCIA_DEBUG
INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
"fdomain_cs.c 1.47 2001/10/13 00:08:52 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
/*====================================================================*/
typedef struct scsi_info_t {
......@@ -213,6 +216,7 @@ static void fdomain_config(dev_link_t *link)
u_char tuple_data[64];
Scsi_Device *dev;
dev_node_t *node, **tail;
char str[16];
struct Scsi_Host *host;
DEBUG(0, "fdomain_config(0x%p)\n", link);
......@@ -253,7 +257,8 @@ static void fdomain_config(dev_link_t *link)
ints[0] = 2;
ints[1] = link->io.BasePort1;
ints[2] = link->irq.AssignedIRQ;
fdomain_setup("PCMCIA setup", ints);
sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ);
fdomain_setup(str, ints);
scsi_register_host(&driver_template);
......
......@@ -503,8 +503,9 @@ static inline void scsi_proc_host_rm(struct Scsi_Host *);
/*
* Prototypes for functions in scsi_scan.c
*/
extern int scsi_add_single_device(uint, uint, uint, uint);
extern int scsi_remove_single_device(uint, uint, uint, uint);
extern struct scsi_device *scsi_add_device(struct Scsi_Host *,
uint, uint, uint);
extern int scsi_remove_device(struct scsi_device *);
extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *);
/*
......
/*
* Copyright (C) 2003 Osamu Tomita <tomita@cinet.co.jp>
*
* PC9801 BIOS geometry handling.
*/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/genhd.h>
#include <linux/blk.h>
#include <asm/pc9800.h>
#include "scsi.h"
#include "hosts.h"
/* XXX - For now, we assume the first (i.e. having the least host_no)
real (i.e. non-emulated) host adapter shall be BIOS-controlled one.
We *SHOULD* invent another way. */
static inline struct Scsi_Host *first_real_host(void)
{
struct Scsi_Host *shost = NULL;
while ((shost = scsi_host_get_next(shost))) {
if (!shost->hostt->emulated)
break;
}
return shost;
}
static int pc98_first_bios_param(struct scsi_device *sdev, int *ip)
{
const u8 *p = (&__PC9800SCA(u8, PC9800SCA_SCSI_PARAMS) + sdev->id * 4);
ip[0] = p[1]; /* # of heads */
ip[1] = p[0]; /* # of sectors/track */
ip[2] = *(u16 *)&p[2] & 0x0fff; /* # of cylinders */
if (p[3] & (1 << 6)) { /* #-of-cylinders is 16-bit */
ip[2] |= (ip[0] & 0xf0) << 8;
ip[0] &= 0x0f;
}
return 0;
}
int pc98_bios_param(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int *ip)
{
static struct Scsi_Host *first_real = first_real_host();
if (sdev->host == first_real && sdev->id < 7 &&
__PC9800SCA_TEST_BIT(PC9800SCA_DISK_EQUIPS, sdev->id))
return pc98_first_bios_param(sdev, ip);
/* Assume PC-9801-92 compatible parameters for HAs without BIOS. */
ip[0] = 8;
ip[1] = 32;
ip[2] = capacity / (8 * 32);
if (ip[2] > 65535) { /* if capacity >= 8GB */
/* Recent on-board adapters seem to use this parameter. */
ip[1] = 128;
ip[2] = capacity / (8 * 128);
if (ip[2] > 65535) { /* if capacity >= 32GB */
/* Clip the number of cylinders. Currently
this is the limit that we deal with. */
ip[2] = 65535;
}
}
return 0;
}
EXPORT_SYMBOL(pc98_bios_param);
......@@ -398,6 +398,50 @@ static void scsi_dump_status(int level)
}
#endif /* CONFIG_SCSI_LOGGING */
static int scsi_add_single_device(uint host, uint channel, uint id, uint lun)
{
struct Scsi_Host *shost;
struct scsi_device *sdev;
int error = -ENODEV;
shost = scsi_host_hn_get(host);
if (!shost)
return -ENODEV;
if (!scsi_find_device(shost, channel, id, lun)) {
sdev = scsi_add_device(shost, channel, id, lun);
if (IS_ERR(sdev))
error = PTR_ERR(sdev);
else
error = 0;
}
scsi_host_put(shost);
return error;
}
static int scsi_remove_single_device(uint host, uint channel, uint id, uint lun)
{
struct scsi_device *sdev;
struct Scsi_Host *shost;
int error = -ENODEV;
shost = scsi_host_hn_get(host);
if (!shost)
return -ENODEV;
sdev = scsi_find_device(shost, channel, id, lun);
if (!sdev)
goto out;
if (sdev->access_count)
goto out;
error = scsi_remove_device(sdev);
out:
scsi_host_put(shost);
return error;
}
static int proc_scsi_gen_write(struct file * file, const char * buf,
unsigned long length, void *data)
{
......
......@@ -189,6 +189,8 @@ struct dev_info scsi_static_device_list[] __initdata = {
{"HITACHI", "DF500", "*", BLIST_SPARSELUN},
{"HITACHI", "DF600", "*", BLIST_SPARSELUN},
{"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
{"SUN", "T300", "*", BLIST_SPARSELUN},
{"SUN", "T4", "*", BLIST_SPARSELUN},
{ NULL, NULL, NULL, 0 },
};
......@@ -1259,14 +1261,6 @@ static int scsi_add_lun(Scsi_Device *sdev, Scsi_Request *sreq,
return SCSI_SCAN_LUN_PRESENT;
}
static void scsi_remove_lun(struct scsi_device *sdev)
{
devfs_unregister(sdev->de);
scsi_device_unregister(sdev);
scsi_free_sdev(sdev);
}
/**
* scsi_probe_and_add_lun - probe a LUN, if a LUN is found add it
* @sdevscan: probe the LUN corresponding to this Scsi_Device
......@@ -1284,90 +1278,77 @@ static void scsi_remove_lun(struct scsi_device *sdev)
* SCSI_SCAN_LUN_PRESENT: a new Scsi_Device was allocated and initialized
**/
static int scsi_probe_and_add_lun(struct Scsi_Host *host,
struct request_queue **q, uint channel, uint id,
uint lun, int *bflagsp)
struct request_queue **q, uint channel, uint id, uint lun,
int *bflagsp, struct scsi_device **sdevp)
{
Scsi_Device *sdev = NULL;
Scsi_Request *sreq = NULL;
unsigned char *scsi_result = NULL;
int bflags;
int res;
struct scsi_device *sdev;
struct scsi_request *sreq;
unsigned char *result;
int bflags, res = SCSI_SCAN_NO_RESPONSE;
sdev = scsi_alloc_sdev(host, q, channel, id, lun);
if (sdev == NULL)
return SCSI_SCAN_NO_RESPONSE;
if (!sdev)
goto out;
sreq = scsi_allocate_request(sdev);
if (sreq == NULL) {
printk(ALLOC_FAILURE_MSG, __FUNCTION__);
res = SCSI_SCAN_NO_RESPONSE;
goto bail_out;
}
if (!sreq)
goto out_free_sdev;
result = kmalloc(256, GFP_ATOMIC |
(host->unchecked_isa_dma) ? __GFP_DMA : 0);
if (!result)
goto out_free_sreq;
scsi_probe_lun(sreq, result, &bflags);
if (sreq->sr_result)
goto out_free_result;
/*
* The sreq is for use only with sdevscan.
* result contains valid SCSI INQUIRY data.
*/
scsi_result = kmalloc(256, GFP_ATOMIC |
(host->unchecked_isa_dma) ?
GFP_DMA : 0);
if (scsi_result == NULL) {
printk(ALLOC_FAILURE_MSG, __FUNCTION__);
res = SCSI_SCAN_NO_RESPONSE;
goto bail_out;
}
scsi_probe_lun(sreq, scsi_result, &bflags);
if (sreq->sr_result)
res = SCSI_SCAN_NO_RESPONSE;
else {
if ((result[0] >> 5) == 3) {
/*
* scsi_result contains valid SCSI INQUIRY data.
* For a Peripheral qualifier 3 (011b), the SCSI
* spec says: The device server is not capable of
* supporting a physical device on this logical
* unit.
*
* For disks, this implies that there is no
* logical disk configured at sdev->lun, but there
* is a target id responding.
*/
if ((scsi_result[0] >> 5) == 3) {
/*
* For a Peripheral qualifier 3 (011b), the SCSI
* spec says: The device server is not capable of
* supporting a physical device on this logical
* unit.
*
* For disks, this implies that there is no
* logical disk configured at sdev->lun, but there
* is a target id responding.
*/
SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO
"scsi scan: peripheral qualifier of 3,"
" no device added\n"));
res = SCSI_SCAN_TARGET_PRESENT;
} else {
res = scsi_add_lun(sdev, sreq, scsi_result, &bflags);
if (res == SCSI_SCAN_LUN_PRESENT) {
if ((bflags & BLIST_KEY) != 0) {
sdev->lockable = 0;
scsi_unlock_floptical(sreq,
scsi_result);
/*
* scsi_result no longer contains
* the INQUIRY data.
*/
}
if (bflagsp != NULL)
*bflagsp = bflags;
}
res = SCSI_SCAN_TARGET_PRESENT;
goto out_free_result;
}
res = scsi_add_lun(sdev, sreq, result, &bflags);
if (res == SCSI_SCAN_LUN_PRESENT) {
if (bflags & BLIST_KEY) {
sdev->lockable = 0;
scsi_unlock_floptical(sreq, result);
}
if (bflagsp)
*bflagsp = bflags;
}
bail_out:
if (scsi_result != NULL)
kfree(scsi_result);
if (sreq != NULL)
scsi_release_request(sreq);
if (res != SCSI_SCAN_LUN_PRESENT) {
if(q) {
out_free_result:
kfree(result);
out_free_sreq:
scsi_release_request(sreq);
out_free_sdev:
if (res == SCSI_SCAN_LUN_PRESENT) {
if (*sdevp)
*sdevp = sdev;
} else {
if (q) {
*q = sdev->request_queue;
sdev->request_queue = NULL;
}
scsi_free_sdev(sdev);
}
out:
return res;
}
/**
......@@ -1453,8 +1434,8 @@ static void scsi_sequential_lun_scan(struct Scsi_Host *shost,
* sparse_lun.
*/
for (lun = 1; lun < max_dev_lun; ++lun)
if ((scsi_probe_and_add_lun(shost, q, channel, id, lun, NULL)
!= SCSI_SCAN_LUN_PRESENT) && !sparse_lun)
if ((scsi_probe_and_add_lun(shost, q, channel, id, lun,
NULL, NULL) != SCSI_SCAN_LUN_PRESENT) && !sparse_lun)
return;
}
......@@ -1669,7 +1650,7 @@ static int scsi_report_lun_scan(Scsi_Device *sdev, struct request_queue **q,
int res;
res = scsi_probe_and_add_lun(sdev->host, q,
sdev->channel, sdev->id, lun, NULL);
sdev->channel, sdev->id, lun, NULL, NULL);
if (res == SCSI_SCAN_NO_RESPONSE) {
/*
* Got some results, but now none, abort.
......@@ -1691,55 +1672,33 @@ static int scsi_report_lun_scan(Scsi_Device *sdev, struct request_queue **q,
}
int scsi_add_single_device(uint host, uint channel, uint id, uint lun)
struct scsi_device *scsi_add_device(struct Scsi_Host *shost,
uint channel, uint id, uint lun)
{
struct Scsi_Host *shost;
int error = -ENODEV;
struct scsi_device *sdev;
int error = -ENODEV, res;
shost = scsi_host_hn_get(host);
if (!shost)
return -ENODEV;
if(scsi_find_device(shost, channel, id, lun) != NULL)
goto out;
res = scsi_probe_and_add_lun(shost, NULL, channel, id, lun,
NULL, &sdev);
if (res == SCSI_SCAN_LUN_PRESENT)
error = scsi_attach_device(sdev);
if (scsi_probe_and_add_lun(shost, NULL, channel, id, lun, NULL) ==
SCSI_SCAN_LUN_PRESENT) {
error = 0;
sdev = scsi_find_device(shost, channel, id, lun);
scsi_attach_device(sdev);
}
out:
scsi_host_put(shost);
return error;
if (error)
sdev = ERR_PTR(error);
return sdev;
}
int scsi_remove_single_device(uint host, uint channel, uint id, uint lun)
int scsi_remove_device(struct scsi_device *sdev)
{
struct scsi_device *sdev;
struct Scsi_Host *shost;
int error = -ENODEV;
shost = scsi_host_hn_get(host);
if (!shost)
return -ENODEV;
sdev = scsi_find_device(shost, channel, id, lun);
if (!sdev)
goto out;
error = -EBUSY;
if (sdev->access_count)
goto out;
scsi_detach_device(sdev);
if (sdev->attached)
goto out;
return -EINVAL;
scsi_remove_lun(sdev);
error = 0;
devfs_unregister(sdev->de);
scsi_device_unregister(sdev);
out:
scsi_host_put(shost);
return error;
scsi_free_sdev(sdev);
return 0;
}
/**
......@@ -1778,9 +1737,8 @@ static void scsi_scan_target(struct Scsi_Host *shost, struct request_queue **q,
* Scan LUN 0, if there is some response, scan further. Ideally, we
* would not configure LUN 0 until all LUNs are scanned.
*/
res = scsi_probe_and_add_lun(shost, q, channel, id, 0, &bflags);
res = scsi_probe_and_add_lun(shost, q, channel, id, 0, &bflags, &sdev);
if (res == SCSI_SCAN_LUN_PRESENT) {
sdev = scsi_find_device(shost, channel, id, 0);
if (scsi_report_lun_scan(sdev, q, bflags) != 0)
/*
* The REPORT LUN did not scan the target,
......@@ -1846,9 +1804,13 @@ void scsi_scan_host(struct Scsi_Host *shost)
void scsi_forget_host(struct Scsi_Host *shost)
{
struct list_head *le, *lh;
struct scsi_device *sdev;
list_for_each_safe(le, lh, &shost->my_devices)
scsi_remove_lun(list_entry(le, struct scsi_device, siblings));
list_for_each_safe(le, lh, &shost->my_devices) {
sdev = list_entry(le, struct scsi_device, siblings);
scsi_remove_device(sdev);
}
}
/*
......
......@@ -78,6 +78,8 @@ EXPORT_SYMBOL(scsi_slave_attach);
EXPORT_SYMBOL(scsi_slave_detach);
EXPORT_SYMBOL(scsi_device_get);
EXPORT_SYMBOL(scsi_device_put);
EXPORT_SYMBOL(scsi_add_device);
EXPORT_SYMBOL(scsi_remove_device);
EXPORT_SYMBOL(scsi_set_device_offline);
/*
......
......@@ -4,10 +4,13 @@
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
* 1999 Andrew R. Baker (andrewb@uab.edu)
* - Support for 2nd SCSI controller on Indigo2
* 2001 Florian Lohoff (flo@rfc822.org)
* - Delete HPC scatter gather (Read corruption on
* multiple disks)
* - Cleanup wback cache handling
*
* (In all truth, Jed Schimmel wrote all this code.)
*
* $Id: sgiwd93.c,v 1.19 2000/02/04 07:40:47 ralf Exp $
*/
#include <linux/init.h>
#include <linux/types.h>
......@@ -36,32 +39,13 @@
struct hpc_chunk {
struct hpc_dma_desc desc;
unsigned long padding;
u32 _padding; /* align to quadword boundary */
};
struct Scsi_Host *sgiwd93_host = NULL;
struct Scsi_Host *sgiwd93_host1 = NULL;
/* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */
static inline void write_wd33c93_count(const wd33c93_regs regs,
unsigned long value)
{
*regs.SASR = WD_TRANSFER_COUNT_MSB;
*regs.SCMD = ((value >> 16) & 0xff);
*regs.SCMD = ((value >> 8) & 0xff);
*regs.SCMD = ((value >> 0) & 0xff);
}
static inline unsigned long read_wd33c93_count(const wd33c93_regs regs)
{
unsigned long value;
*regs.SASR = WD_TRANSFER_COUNT_MSB;
value = (*regs.SCMD << 16);
value |= (*regs.SCMD << 8);
value |= (*regs.SCMD << 0);
return value;
}
/* XXX woof! */
static void sgiwd93_intr(int irq, void *dev_id, struct pt_regs *regs)
......@@ -82,7 +66,6 @@ void fill_hpc_entries (struct hpc_chunk **hcp, char *addr, unsigned long len)
unsigned long physaddr;
unsigned long count;
dma_cache_wback_inv((unsigned long)addr,len);
physaddr = PHYSADDR(addr);
while (len) {
/*
......@@ -101,7 +84,6 @@ void fill_hpc_entries (struct hpc_chunk **hcp, char *addr, unsigned long len)
static int dma_setup(Scsi_Cmnd *cmd, int datainp)
{
struct WD33C93_hostdata *hdata = (struct WD33C93_hostdata *)cmd->host->hostdata;
const wd33c93_regs regs = hdata->regs;
struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) cmd->host->base;
struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->dma_bounce_buffer;
......@@ -112,46 +94,17 @@ static int dma_setup(Scsi_Cmnd *cmd, int datainp)
hdata->dma_dir = datainp;
if(cmd->SCp.buffers_residual) {
struct scatterlist *slp = cmd->SCp.buffer;
int i, totlen = 0;
/*
* wd33c93 shouldn't pass us bogus dma_setups, but
* it does:-( The other wd33c93 drivers deal with
* it the same way (which isn't that obvious).
* IMHO a better fix would be, not to do these
* dma setups in the first place
*/
if (cmd->SCp.ptr == NULL)
return 1;
#ifdef DEBUG_DMA
printk("SCLIST<");
#endif
for(i = 0; i <= cmd->SCp.buffers_residual; i++) {
#ifdef DEBUG_DMA
printk("[%p,%d]",
page_address(slp[i].page) + slp[i].offset,
slp[i].length);
#endif
fill_hpc_entries (&hcp,
page_address(slp[i].page) + slp[i].offset,
slp[i].length);
totlen += slp[i].length;
}
#ifdef DEBUG_DMA
printk(">tlen<%d>", totlen);
#endif
hdata->dma_bounce_len = totlen; /* a trick... */
write_wd33c93_count(regs, totlen);
} else {
/* Non-scattered dma. */
#ifdef DEBUG_DMA
printk("ONEBUF<%p,%d>", cmd->SCp.ptr, cmd->SCp.this_residual);
#endif
/*
* wd33c93 shouldn't pass us bogus dma_setups, but
* it does:-( The other wd33c93 drivers deal with
* it the same way (which isn't that obvious).
* IMHO a better fix would be, not to do these
* dma setups in the first place
*/
if (cmd->SCp.ptr == NULL)
return 1;
fill_hpc_entries (&hcp, cmd->SCp.ptr,cmd->SCp.this_residual);
write_wd33c93_count(regs, cmd->SCp.this_residual);
}
fill_hpc_entries (&hcp, cmd->SCp.ptr,cmd->SCp.this_residual);
/* To make sure, if we trip an HPC bug, that we transfer
* every single byte, we tag on an extra zero length dma
......@@ -166,10 +119,14 @@ static int dma_setup(Scsi_Cmnd *cmd, int datainp)
/* Start up the HPC. */
hregs->ndptr = PHYSADDR(hdata->dma_bounce_buffer);
if(datainp)
if(datainp) {
dma_cache_inv((unsigned long) cmd->SCp.ptr, cmd->SCp.this_residual);
hregs->ctrl = (HPC3_SCTRL_ACTIVE);
else
} else {
dma_cache_wback_inv((unsigned long) cmd->SCp.ptr, cmd->SCp.this_residual);
hregs->ctrl = (HPC3_SCTRL_ACTIVE | HPC3_SCTRL_DIR);
}
return 0;
}
......@@ -177,7 +134,6 @@ static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *SCpnt,
int status)
{
struct WD33C93_hostdata *hdata = (struct WD33C93_hostdata *)instance->hostdata;
const wd33c93_regs regs = hdata->regs;
struct hpc3_scsiregs *hregs;
if (!SCpnt)
......@@ -197,44 +153,6 @@ static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *SCpnt,
}
hregs->ctrl = 0;
/* See how far we got and update scatterlist state if necessary. */
if(SCpnt->SCp.buffers_residual) {
struct scatterlist *slp = SCpnt->SCp.buffer;
int totlen, wd93_residual, transferred, i;
/* Yep, we were doing the scatterlist thang. */
totlen = hdata->dma_bounce_len;
wd93_residual = read_wd33c93_count(regs);
transferred = totlen - wd93_residual;
#ifdef DEBUG_DMA
printk("tlen<%d>resid<%d>transf<%d> ",
totlen, wd93_residual, transferred);
#endif
/* Avoid long winded partial-transfer search for common case. */
if(transferred != totlen) {
/* This is the nut case. */
#ifdef DEBUG_DMA
printk("Jed was here...");
#endif
for(i = 0; i <= SCpnt->SCp.buffers_residual; i++) {
if(slp[i].length >= transferred)
break;
transferred -= slp[i].length;
}
} else {
/* This is the common case. */
#ifdef DEBUG_DMA
printk("did it all...");
#endif
i = SCpnt->SCp.buffers_residual;
}
SCpnt->SCp.buffer = &slp[i];
SCpnt->SCp.buffers_residual = SCpnt->SCp.buffers_residual - i;
SCpnt->SCp.ptr = (char *) page_address(slp[i].page) + slp[i].offset;
SCpnt->SCp.this_residual = slp[i].length;
}
#ifdef DEBUG_DMA
printk("\n");
#endif
......@@ -264,6 +182,9 @@ static inline void init_hpc_chain(uchar *buf)
};
hcp--;
hcp->desc.pnext = PHYSADDR(buf);
/* Force flush to memory */
dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE);
}
int __init sgiwd93_detect(Scsi_Host_Template *SGIblows)
......@@ -273,8 +194,8 @@ int __init sgiwd93_detect(Scsi_Host_Template *SGIblows)
struct hpc3_scsiregs *hregs1 = &hpc3c0->scsi_chan1;
struct WD33C93_hostdata *hdata;
struct WD33C93_hostdata *hdata1;
uchar *buf;
wd33c93_regs regs;
uchar *buf;
if(called)
return 0; /* Should bitch on the console about this... */
......@@ -294,10 +215,10 @@ int __init sgiwd93_detect(Scsi_Host_Template *SGIblows)
return 0;
}
init_hpc_chain(buf);
dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE);
/* HPC_SCSI_REG0 | 0x03 | KSEG1 */
regs.SASR = (volatile unsigned char *)KSEG1ADDR (0x1fbc0003);
regs.SCMD = (volatile unsigned char *)KSEG1ADDR (0x1fbc0007);
regs.SASR = (unsigned char*) KSEG1ADDR (0x1fbc0003);
regs.SCMD = (unsigned char*) KSEG1ADDR (0x1fbc0007);
wd33c93_init(sgiwd93_host, regs, dma_setup, dma_stop, WD33C93_FS_16_20);
hdata = (struct WD33C93_hostdata *)sgiwd93_host->hostdata;
......@@ -329,17 +250,16 @@ int __init sgiwd93_detect(Scsi_Host_Template *SGIblows)
return 1; /* We registered host0 so return success*/
}
init_hpc_chain(buf);
dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE);
/* HPC_SCSI_REG1 | 0x03 | KSEG1 */
regs.SASR = (volatile unsigned char *)KSEG1ADDR (0x1fbc8003);
regs.SCMD = (volatile unsigned char *)KSEG1ADDR (0x1fbc8007);
regs.SASR = (unsigned char*) KSEG1ADDR(0x1fbc8003);
regs.SCMD = (unsigned char*) KSEG1ADDR(0x1fbc8007);
wd33c93_init(sgiwd93_host1, regs, dma_setup, dma_stop,
WD33C93_FS_16_20);
WD33C93_FS_16_20);
hdata1 = (struct WD33C93_hostdata *)sgiwd93_host1->hostdata;
hdata1->no_sync = 0;
hdata1->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf));
dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE);
if (request_irq(SGI_WD93_1_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host1)) {
printk(KERN_WARNING "sgiwd93: Could not allocate irq %d (for host1).\n", SGI_WD93_1_IRQ);
......
......@@ -543,7 +543,7 @@ static int sun3scsi_dma_finish(int write_flag)
#if 1
// check to empty the fifo on a read
if(!write_flag) {
int tmo = 200000; /* 2 sec */
int tmo = 20000; /* .2 sec */
while(1) {
if(dregs->csr & CSR_FIFO_EMPTY)
......
......@@ -6984,7 +6984,7 @@ static void ncr_soft_reset(ncb_p np)
INW (nc_sist);
}
else if (istat & DIP) {
if (INB (nc_dstat) & ABRT);
if (INB (nc_dstat) & ABRT)
break;
}
UDELAY(5);
......
......@@ -125,7 +125,7 @@ void sym_mdelay(int ms) { mdelay(ms); }
*
* The whole SCSI sub-system under Linux is basically single-threaded.
* Everything, including low-level driver interrupt routine, happens
* whith the `io_request_lock' held.
* with the `io_request_lock' held.
* The sym53c8xx-1.x drivers series ran their interrupt code using a
* spin mutex per controller. This added complexity without improving
* scalability significantly. the sym-2 driver still use a spinlock
......
......@@ -234,7 +234,7 @@ static void sym_soft_reset (hcb_p np)
INW (nc_sist);
}
else if (istat & DIP) {
if (INB (nc_dstat) & ABRT);
if (INB (nc_dstat) & ABRT)
break;
}
UDELAY(5);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
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