提交 4adea1fd 编写于 作者: L Linus Torvalds

Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi

Pull more SCSI updates from James Bottomley:
 "This is mostly stuff which missed the first pull request because it
  needed to incubate longer.  It's mainly made up of the ncr 5380 rework
  but also has a few assorted bug fixes"

* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (88 commits)
  imm: Use new parport device model
  megaraid: Fix possible NULL pointer deference in mraid_mm_ioctl
  storvsc: Fix typo in MODULE_PARM_DESC
  cxgbi: Typo in MODULE_PARM_DESC
  3w-xxxx: Pass through compat mode ioctls
  hisi_sas: Use u64 for qw0 in free_device_v1_hw()
  hisi_sas: Fix typo in setup_itct_v1_hw()
  hisi_sas: Fix v1 itct masks
  ipr: Fix out-of-bounds null overwrite
  scsi: add Synology to 1024 sector blacklist
  ncr5380: Add support for HP C2502
  ncr5380: Fix wait for 53C80 registers registers after PDMA
  ncr5380: Enable PDMA for DTC chips
  ncr5380: Enable PDMA for NCR53C400A
  ncr5380: Use runtime register mapping
  ncr5380: Fix pseudo DMA transfers on 53C400
  ncr5380: Cleanup whitespace and parentheses
  atari_NCR5380: Merge changes from NCR5380.c
  ncr5380: Merge changes from atari_NCR5380.c
  ncr5380: Fix whitespace in comments using regexp
  ...
......@@ -1045,6 +1045,9 @@ static int tw_chrdev_open(struct inode *inode, struct file *file)
static const struct file_operations tw_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = tw_chrdev_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = tw_chrdev_ioctl,
#endif
.open = tw_chrdev_open,
.release = NULL,
.llseek = noop_llseek,
......
......@@ -1620,23 +1620,6 @@ config ATARI_SCSI
ST-DMA, replacing ACSI). It does NOT support other schemes, like
in the Hades (without DMA).
config ATARI_SCSI_TOSHIBA_DELAY
bool "Long delays for Toshiba CD-ROMs"
depends on ATARI_SCSI
help
This option increases the delay after a SCSI arbitration to
accommodate some flaky Toshiba CD-ROM drives. Say Y if you intend to
use a Toshiba CD-ROM drive; otherwise, the option is not needed and
would impact performance a bit, so say N.
config ATARI_SCSI_RESET_BOOT
bool "Reset SCSI-devices at boottime"
depends on ATARI_SCSI
help
Reset the devices on your Atari whenever it boots. This makes the
boot process fractionally longer but may assist recovery from errors
that leave the devices with SCSI operations partway completed.
config MAC_SCSI
tristate "Macintosh NCR5380 SCSI"
depends on MAC && SCSI=y
......
此差异已折叠。
......@@ -22,8 +22,13 @@
#ifndef NCR5380_H
#define NCR5380_H
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/workqueue.h>
#include <scsi/scsi_dbg.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_transport_spi.h>
#define NDEBUG_ARBITRATION 0x1
#define NDEBUG_AUTOSENSE 0x2
......@@ -158,8 +163,7 @@
/* Write any value to this register to start an ini mode DMA receive */
#define START_DMA_INITIATOR_RECEIVE_REG 7 /* wo */
#define C400_CONTROL_STATUS_REG NCR53C400_register_offset-8 /* rw */
/* NCR 53C400(A) Control Status Register bits: */
#define CSR_RESET 0x80 /* wo Resets 53c400 */
#define CSR_53C80_REG 0x80 /* ro 5380 registers busy */
#define CSR_TRANS_DIR 0x40 /* rw Data transfer direction */
......@@ -176,16 +180,6 @@
#define CSR_BASE CSR_53C80_INTR
#endif
/* Number of 128-byte blocks to be transferred */
#define C400_BLOCK_COUNTER_REG NCR53C400_register_offset-7 /* rw */
/* Resume transfer after disconnect */
#define C400_RESUME_TRANSFER_REG NCR53C400_register_offset-6 /* wo */
/* Access to host buffer stack */
#define C400_HOST_BUFFER NCR53C400_register_offset-4 /* rw */
/* Note : PHASE_* macros are based on the values of the STATUS register */
#define PHASE_MASK (SR_MSG | SR_CD | SR_IO)
......@@ -205,16 +199,6 @@
#define PHASE_SR_TO_TCR(phase) ((phase) >> 2)
/*
* The internal should_disconnect() function returns these based on the
* expected length of a disconnect if a device supports disconnect/
* reconnect.
*/
#define DISCONNECT_NONE 0
#define DISCONNECT_TIME_TO_DATA 1
#define DISCONNECT_LONG 2
/*
* "Special" value for the (unsigned char) command tag, to indicate
* I_T_L nexus instead of I_T_L_Q.
......@@ -236,15 +220,11 @@
#define NO_IRQ 0
#endif
#define FLAG_HAS_LAST_BYTE_SENT 1 /* NCR53c81 or better */
#define FLAG_CHECK_LAST_BYTE_SENT 2 /* Only test once */
#define FLAG_NCR53C400 4 /* NCR53c400 */
#define FLAG_NO_DMA_FIXUP 1 /* No DMA errata workarounds */
#define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */
#define FLAG_DTC3181E 16 /* DTC3181E */
#define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */
#define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */
#ifndef ASM
#define FLAG_TOSHIBA_DELAY 128 /* Allow for borken CD-ROMs */
#ifdef SUPPORT_TAGS
struct tag_alloc {
......@@ -258,33 +238,24 @@ struct NCR5380_hostdata {
NCR5380_implementation_fields; /* implementation specific */
struct Scsi_Host *host; /* Host backpointer */
unsigned char id_mask, id_higher_mask; /* 1 << id, all bits greater */
unsigned char targets_present; /* targets we have connected
to, so we can call a select
failure a retryable condition */
volatile unsigned char busy[8]; /* index = target, bit = lun */
unsigned char busy[8]; /* index = target, bit = lun */
#if defined(REAL_DMA) || defined(REAL_DMA_POLL)
volatile int dma_len; /* requested length of DMA */
int dma_len; /* requested length of DMA */
#endif
volatile unsigned char last_message; /* last message OUT */
volatile struct scsi_cmnd *connected; /* currently connected command */
volatile struct scsi_cmnd *issue_queue; /* waiting to be issued */
volatile struct scsi_cmnd *disconnected_queue; /* waiting for reconnect */
volatile int restart_select; /* we have disconnected,
used to restart
NCR5380_select() */
volatile unsigned aborted:1; /* flag, says aborted */
unsigned char last_message; /* last message OUT */
struct scsi_cmnd *connected; /* currently connected cmnd */
struct scsi_cmnd *selecting; /* cmnd to be connected */
struct list_head unissued; /* waiting to be issued */
struct list_head autosense; /* priority issue queue */
struct list_head disconnected; /* waiting for reconnect */
spinlock_t lock; /* protects this struct */
int flags;
unsigned long time_expires; /* in jiffies, set prior to sleeping */
int select_time; /* timer in select for target response */
volatile struct scsi_cmnd *selecting;
struct delayed_work coroutine; /* our co-routine */
struct scsi_eh_save ses;
struct scsi_cmnd *sensing;
char info[256];
int read_overruns; /* number of bytes to cut from a
* transfer to handle chip overruns */
int retain_dma_intr;
struct work_struct main_task;
volatile int main_running;
#ifdef SUPPORT_TAGS
struct tag_alloc TagAlloc[8][8]; /* 8 targets and 8 LUNs */
#endif
......@@ -292,10 +263,23 @@ struct NCR5380_hostdata {
unsigned spin_max_r;
unsigned spin_max_w;
#endif
struct workqueue_struct *work_q;
unsigned long accesses_per_ms; /* chip register accesses per ms */
};
#ifdef __KERNEL__
struct NCR5380_cmd {
struct list_head list;
};
#define NCR5380_CMD_SIZE (sizeof(struct NCR5380_cmd))
static inline struct scsi_cmnd *NCR5380_to_scmd(struct NCR5380_cmd *ncmd_ptr)
{
return ((struct scsi_cmnd *)ncmd_ptr) - 1;
}
#ifndef NDEBUG
#define NDEBUG (0)
#endif
......@@ -304,6 +288,11 @@ struct NCR5380_hostdata {
do { if ((NDEBUG) & (flg)) \
printk(KERN_DEBUG fmt, ## __VA_ARGS__); } while (0)
#define dsprintk(flg, host, fmt, ...) \
do { if ((NDEBUG) & (flg)) \
shost_printk(KERN_DEBUG, host, fmt, ## __VA_ARGS__); \
} while (0)
#if NDEBUG
#define NCR5380_dprint(flg, arg) \
do { if ((NDEBUG) & (flg)) NCR5380_print(arg); } while (0)
......@@ -320,6 +309,7 @@ static void NCR5380_print(struct Scsi_Host *instance);
static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible);
#endif
static int NCR5380_init(struct Scsi_Host *instance, int flags);
static int NCR5380_maybe_reset_bus(struct Scsi_Host *);
static void NCR5380_exit(struct Scsi_Host *instance);
static void NCR5380_information_transfer(struct Scsi_Host *instance);
#ifndef DONT_USE_INTR
......@@ -328,7 +318,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id);
static void NCR5380_main(struct work_struct *work);
static const char *NCR5380_info(struct Scsi_Host *instance);
static void NCR5380_reselect(struct Scsi_Host *instance);
static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd);
static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *);
#if defined(PSEUDO_DMA) || defined(REAL_DMA) || defined(REAL_DMA_POLL)
static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data);
#endif
......@@ -443,5 +433,4 @@ static __inline__ int NCR5380_pc_dma_residual(struct Scsi_Host *instance)
#endif /* defined(i386) || defined(__alpha__) */
#endif /* defined(REAL_DMA) */
#endif /* __KERNEL__ */
#endif /* ndef ASM */
#endif /* NCR5380_H */
......@@ -4,9 +4,7 @@
* Copyright 1995-2002, Russell King
*/
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/blkdev.h>
#include <linux/init.h>
......@@ -15,15 +13,14 @@
#include <scsi/scsi_host.h>
#include <scsi/scsicam.h>
#define PSEUDO_DMA
#define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata)
#define NCR5380_local_declare() struct Scsi_Host *_instance
#define NCR5380_setup(instance) _instance = instance
#define NCR5380_read(reg) cumanascsi_read(_instance, reg)
#define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value)
#define NCR5380_read(reg) cumanascsi_read(instance, reg)
#define NCR5380_write(reg, value) cumanascsi_write(instance, reg, value)
#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize)
#define NCR5380_intr cumanascsi_intr
#define NCR5380_queue_command cumanascsi_queue_command
#define NCR5380_info cumanascsi_info
......@@ -211,6 +208,8 @@ static struct scsi_host_template cumanascsi_template = {
.cmd_per_lun = 2,
.use_clustering = DISABLE_CLUSTERING,
.proc_name = "CumanaSCSI-1",
.cmd_size = NCR5380_CMD_SIZE,
.max_sectors = 128,
};
static int cumanascsi1_probe(struct expansion_card *ec,
......@@ -240,23 +239,21 @@ static int cumanascsi1_probe(struct expansion_card *ec,
host->irq = ec->irq;
NCR5380_init(host, 0);
ret = NCR5380_init(host, 0);
if (ret)
goto out_unmap;
NCR5380_maybe_reset_bus(host);
priv(host)->ctrl = 0;
writeb(0, priv(host)->base + CTRL);
host->n_io_port = 255;
if (!(request_region(host->io_port, host->n_io_port, "CumanaSCSI-1"))) {
ret = -EBUSY;
goto out_unmap;
}
ret = request_irq(host->irq, cumanascsi_intr, 0,
"CumanaSCSI-1", host);
if (ret) {
printk("scsi%d: IRQ%d not free: %d\n",
host->host_no, host->irq, ret);
goto out_unmap;
goto out_exit;
}
ret = scsi_add_host(host, &ec->dev);
......@@ -268,6 +265,8 @@ static int cumanascsi1_probe(struct expansion_card *ec,
out_free_irq:
free_irq(host->irq, host);
out_exit:
NCR5380_exit(host);
out_unmap:
iounmap(priv(host)->base);
iounmap(priv(host)->dma);
......
......@@ -5,9 +5,7 @@
*/
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/blkdev.h>
#include <linux/init.h>
......@@ -20,14 +18,16 @@
#define DONT_USE_INTR
#define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata)
#define NCR5380_local_declare() void __iomem *_base
#define NCR5380_setup(host) _base = priv(host)->base
#define NCR5380_read(reg) readb(_base + ((reg) << 2))
#define NCR5380_write(reg, value) writeb(value, _base + ((reg) << 2))
#define NCR5380_read(reg) \
readb(priv(instance)->base + ((reg) << 2))
#define NCR5380_write(reg, value) \
writeb(value, priv(instance)->base + ((reg) << 2))
#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize)
#define NCR5380_queue_command oakscsi_queue_command
#define NCR5380_info oakscsi_info
#define NCR5380_show_info oakscsi_show_info
#define NCR5380_implementation_fields \
void __iomem *base
......@@ -103,7 +103,6 @@ printk("reading %p len %d\n", addr, len);
static struct scsi_host_template oakscsi_template = {
.module = THIS_MODULE,
.show_info = oakscsi_show_info,
.name = "Oak 16-bit SCSI",
.info = oakscsi_info,
.queuecommand = oakscsi_queue_command,
......@@ -115,6 +114,8 @@ static struct scsi_host_template oakscsi_template = {
.cmd_per_lun = 2,
.use_clustering = DISABLE_CLUSTERING,
.proc_name = "oakscsi",
.cmd_size = NCR5380_CMD_SIZE,
.max_sectors = 128,
};
static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
......@@ -142,15 +143,21 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
host->irq = NO_IRQ;
host->n_io_port = 255;
NCR5380_init(host, 0);
ret = NCR5380_init(host, 0);
if (ret)
goto out_unmap;
NCR5380_maybe_reset_bus(host);
ret = scsi_add_host(host, &ec->dev);
if (ret)
goto out_unmap;
goto out_exit;
scsi_scan_host(host);
goto out;
out_exit:
NCR5380_exit(host);
out_unmap:
iounmap(priv(host)->base);
unreg:
......
此差异已折叠。
......@@ -66,7 +66,6 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/blkdev.h>
#include <linux/interrupt.h>
#include <linux/init.h>
......@@ -98,7 +97,6 @@
#define NCR5380_queue_command atari_scsi_queue_command
#define NCR5380_abort atari_scsi_abort
#define NCR5380_show_info atari_scsi_show_info
#define NCR5380_info atari_scsi_info
#define NCR5380_dma_read_setup(instance, data, count) \
......@@ -161,23 +159,10 @@ static inline unsigned long SCSI_DMA_GETADR(void)
return adr;
}
#define HOSTDATA_DMALEN (((struct NCR5380_hostdata *) \
(atari_scsi_host->hostdata))->dma_len)
/* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms,
* we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more
* need ten times the standard value... */
#ifndef CONFIG_ATARI_SCSI_TOSHIBA_DELAY
#define AFTER_RESET_DELAY (HZ/2)
#else
#define AFTER_RESET_DELAY (5*HZ/2)
#endif
#ifdef REAL_DMA
static void atari_scsi_fetch_restbytes(void);
#endif
static struct Scsi_Host *atari_scsi_host;
static unsigned char (*atari_scsi_reg_read)(unsigned char reg);
static void (*atari_scsi_reg_write)(unsigned char reg, unsigned char value);
......@@ -208,12 +193,12 @@ static int setup_cmd_per_lun = -1;
module_param(setup_cmd_per_lun, int, 0);
static int setup_sg_tablesize = -1;
module_param(setup_sg_tablesize, int, 0);
#ifdef SUPPORT_TAGS
static int setup_use_tagged_queuing = -1;
module_param(setup_use_tagged_queuing, int, 0);
#endif
static int setup_hostid = -1;
module_param(setup_hostid, int, 0);
static int setup_toshiba_delay = -1;
module_param(setup_toshiba_delay, int, 0);
#if defined(REAL_DMA)
......@@ -273,15 +258,17 @@ static void scsi_dma_buserr(int irq, void *dummy)
#endif
static irqreturn_t scsi_tt_intr(int irq, void *dummy)
static irqreturn_t scsi_tt_intr(int irq, void *dev)
{
#ifdef REAL_DMA
struct Scsi_Host *instance = dev;
struct NCR5380_hostdata *hostdata = shost_priv(instance);
int dma_stat;
dma_stat = tt_scsi_dma.dma_ctrl;
dprintk(NDEBUG_INTR, "scsi%d: NCR5380 interrupt, DMA status = %02x\n",
atari_scsi_host->host_no, dma_stat & 0xff);
dsprintk(NDEBUG_INTR, instance, "NCR5380 interrupt, DMA status = %02x\n",
dma_stat & 0xff);
/* Look if it was the DMA that has interrupted: First possibility
* is that a bus error occurred...
......@@ -304,7 +291,8 @@ static irqreturn_t scsi_tt_intr(int irq, void *dummy)
* data reg!
*/
if ((dma_stat & 0x02) && !(dma_stat & 0x40)) {
atari_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P(dma_addr) - atari_dma_startaddr);
atari_dma_residual = hostdata->dma_len -
(SCSI_DMA_READ_P(dma_addr) - atari_dma_startaddr);
dprintk(NDEBUG_DMA, "SCSI DMA: There are %ld residual bytes.\n",
atari_dma_residual);
......@@ -356,15 +344,17 @@ static irqreturn_t scsi_tt_intr(int irq, void *dummy)
#endif /* REAL_DMA */
NCR5380_intr(irq, dummy);
NCR5380_intr(irq, dev);
return IRQ_HANDLED;
}
static irqreturn_t scsi_falcon_intr(int irq, void *dummy)
static irqreturn_t scsi_falcon_intr(int irq, void *dev)
{
#ifdef REAL_DMA
struct Scsi_Host *instance = dev;
struct NCR5380_hostdata *hostdata = shost_priv(instance);
int dma_stat;
/* Turn off DMA and select sector counter register before
......@@ -399,7 +389,7 @@ static irqreturn_t scsi_falcon_intr(int irq, void *dummy)
printk(KERN_ERR "SCSI DMA error: %ld bytes lost in "
"ST-DMA fifo\n", transferred & 15);
atari_dma_residual = HOSTDATA_DMALEN - transferred;
atari_dma_residual = hostdata->dma_len - transferred;
dprintk(NDEBUG_DMA, "SCSI DMA: There are %ld residual bytes.\n",
atari_dma_residual);
} else
......@@ -411,13 +401,14 @@ static irqreturn_t scsi_falcon_intr(int irq, void *dummy)
* data to the original destination address.
*/
memcpy(atari_dma_orig_addr, phys_to_virt(atari_dma_startaddr),
HOSTDATA_DMALEN - atari_dma_residual);
hostdata->dma_len - atari_dma_residual);
atari_dma_orig_addr = NULL;
}
#endif /* REAL_DMA */
NCR5380_intr(irq, dummy);
NCR5380_intr(irq, dev);
return IRQ_HANDLED;
}
......@@ -488,7 +479,7 @@ static int __init atari_scsi_setup(char *str)
* Defaults depend on TT or Falcon, determined at run time.
* Negative values mean don't change.
*/
int ints[6];
int ints[8];
get_options(str, ARRAY_SIZE(ints), ints);
......@@ -504,10 +495,11 @@ static int __init atari_scsi_setup(char *str)
setup_sg_tablesize = ints[3];
if (ints[0] >= 4)
setup_hostid = ints[4];
#ifdef SUPPORT_TAGS
if (ints[0] >= 5)
setup_use_tagged_queuing = ints[5];
#endif
/* ints[6] (use_pdma) is ignored */
if (ints[0] >= 7)
setup_toshiba_delay = ints[7];
return 1;
}
......@@ -516,38 +508,6 @@ __setup("atascsi=", atari_scsi_setup);
#endif /* !MODULE */
#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
static void __init atari_scsi_reset_boot(void)
{
unsigned long end;
/*
* Do a SCSI reset to clean up the bus during initialization. No messing
* with the queues, interrupts, or locks necessary here.
*/
printk("Atari SCSI: resetting the SCSI bus...");
/* get in phase */
NCR5380_write(TARGET_COMMAND_REG,
PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG)));
/* assert RST */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);
/* The min. reset hold time is 25us, so 40us should be enough */
udelay(50);
/* reset RST and interrupt */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
NCR5380_read(RESET_PARITY_INTERRUPT_REG);
end = jiffies + AFTER_RESET_DELAY;
while (time_before(jiffies, end))
barrier();
printk(" done\n");
}
#endif
#if defined(REAL_DMA)
static unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance,
......@@ -815,14 +775,14 @@ static int atari_scsi_bus_reset(struct scsi_cmnd *cmd)
static struct scsi_host_template atari_scsi_template = {
.module = THIS_MODULE,
.proc_name = DRV_MODULE_NAME,
.show_info = atari_scsi_show_info,
.name = "Atari native SCSI",
.info = atari_scsi_info,
.queuecommand = atari_scsi_queue_command,
.eh_abort_handler = atari_scsi_abort,
.eh_bus_reset_handler = atari_scsi_bus_reset,
.this_id = 7,
.use_clustering = DISABLE_CLUSTERING
.use_clustering = DISABLE_CLUSTERING,
.cmd_size = NCR5380_CMD_SIZE,
};
static int __init atari_scsi_probe(struct platform_device *pdev)
......@@ -880,7 +840,7 @@ static int __init atari_scsi_probe(struct platform_device *pdev)
} else {
/* Test if a host id is set in the NVRam */
if (ATARIHW_PRESENT(TT_CLK) && nvram_check_checksum()) {
unsigned char b = nvram_read_byte(14);
unsigned char b = nvram_read_byte(16);
/* Arbitration enabled? (for TOS)
* If yes, use configured host ID
......@@ -915,21 +875,18 @@ static int __init atari_scsi_probe(struct platform_device *pdev)
error = -ENOMEM;
goto fail_alloc;
}
atari_scsi_host = instance;
#ifdef CONFIG_ATARI_SCSI_RESET_BOOT
atari_scsi_reset_boot();
#endif
instance->irq = irq->start;
host_flags |= IS_A_TT() ? 0 : FLAG_LATE_DMA_SETUP;
#ifdef SUPPORT_TAGS
host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0;
#endif
host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0;
NCR5380_init(instance, host_flags);
error = NCR5380_init(instance, host_flags);
if (error)
goto fail_init;
if (IS_A_TT()) {
error = request_irq(instance->irq, scsi_tt_intr, 0,
......@@ -975,6 +932,8 @@ static int __init atari_scsi_probe(struct platform_device *pdev)
#endif
}
NCR5380_maybe_reset_bus(instance);
error = scsi_add_host(instance, NULL);
if (error)
goto fail_host;
......@@ -989,6 +948,7 @@ static int __init atari_scsi_probe(struct platform_device *pdev)
free_irq(instance->irq, instance);
fail_irq:
NCR5380_exit(instance);
fail_init:
scsi_host_put(instance);
fail_alloc:
if (atari_dma_buffer)
......
......@@ -57,7 +57,7 @@ MODULE_PARM_DESC(cxgb3i_snd_win, "TCP send window in bytes (default=128KB)");
static int cxgb3i_rx_credit_thres = 10 * 1024;
module_param(cxgb3i_rx_credit_thres, int, 0644);
MODULE_PARM_DESC(rx_credit_thres,
MODULE_PARM_DESC(cxgb3i_rx_credit_thres,
"RX credits return threshold in bytes (default=10KB)");
static unsigned int cxgb3i_max_connect = 8 * 1024;
......
......@@ -36,17 +36,10 @@
#define DONT_USE_INTR
#define NCR5380_read(reg) inb(port + reg)
#define NCR5380_write(reg, value) outb(value, port + reg)
#define NCR5380_read(reg) inb(instance->io_port + reg)
#define NCR5380_write(reg, value) outb(value, instance->io_port + reg)
#define NCR5380_implementation_fields /* none */
#define NCR5380_local_declare() unsigned int port
#define NCR5380_setup(instance) port = instance->io_port
/*
* Includes needed for NCR5380.[ch] (XXX: Move them to NCR5380.h)
*/
#include <linux/delay.h>
#include "NCR5380.h"
#include "NCR5380.c"
......@@ -56,6 +49,7 @@
static struct scsi_host_template dmx3191d_driver_template = {
.module = THIS_MODULE,
.proc_name = DMX3191D_DRIVER_NAME,
.name = "Domex DMX3191D",
.info = NCR5380_info,
......@@ -67,6 +61,8 @@ static struct scsi_host_template dmx3191d_driver_template = {
.sg_tablesize = SG_ALL,
.cmd_per_lun = 2,
.use_clustering = DISABLE_CLUSTERING,
.cmd_size = NCR5380_CMD_SIZE,
.max_sectors = 128,
};
static int dmx3191d_probe_one(struct pci_dev *pdev,
......@@ -97,17 +93,25 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
*/
shost->irq = NO_IRQ;
NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E);
error = NCR5380_init(shost, FLAG_NO_PSEUDO_DMA);
if (error)
goto out_host_put;
NCR5380_maybe_reset_bus(shost);
pci_set_drvdata(pdev, shost);
error = scsi_add_host(shost, &pdev->dev);
if (error)
goto out_release_region;
goto out_exit;
scsi_scan_host(shost);
return 0;
out_exit:
NCR5380_exit(shost);
out_host_put:
scsi_host_put(shost);
out_release_region:
release_region(io, DMX3191D_REGION_LEN);
out_disable_device:
......@@ -119,15 +123,14 @@ static int dmx3191d_probe_one(struct pci_dev *pdev,
static void dmx3191d_remove_one(struct pci_dev *pdev)
{
struct Scsi_Host *shost = pci_get_drvdata(pdev);
unsigned long io = shost->io_port;
scsi_remove_host(shost);
NCR5380_exit(shost);
release_region(shost->io_port, DMX3191D_REGION_LEN);
pci_disable_device(pdev);
scsi_host_put(shost);
release_region(io, DMX3191D_REGION_LEN);
pci_disable_device(pdev);
}
static struct pci_device_id dmx3191d_pci_tbl[] = {
......
#define PSEUDO_DMA
#define DONT_USE_INTR
#define UNSAFE /* Leave interrupts enabled during pseudo-dma I/O */
#define DMA_WORKS_RIGHT
/*
* DTC 3180/3280 driver, by
......@@ -50,15 +46,13 @@
#include <linux/module.h>
#include <linux/signal.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <scsi/scsi_host.h>
#include "dtc.h"
#define AUTOPROBE_IRQ
#include "NCR5380.h"
......@@ -150,7 +144,7 @@ static const struct signature {
static int __init dtc_setup(char *str)
{
static int commandline_current = 0;
static int commandline_current;
int i;
int ints[10];
......@@ -188,7 +182,7 @@ __setup("dtc=", dtc_setup);
static int __init dtc_detect(struct scsi_host_template * tpnt)
{
static int current_override = 0, current_base = 0;
static int current_override, current_base;
struct Scsi_Host *instance;
unsigned int addr;
void __iomem *base;
......@@ -205,9 +199,8 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
addr = 0;
} else
for (; !addr && (current_base < NO_BASES); ++current_base) {
#if (DTCDEBUG & DTCDEBUG_INIT)
printk(KERN_DEBUG "scsi-dtc : probing address %08x\n", bases[current_base].address);
#endif
dprintk(NDEBUG_INIT, "dtc: probing address 0x%08x\n",
(unsigned int)bases[current_base].address);
if (bases[current_base].noauto)
continue;
base = ioremap(bases[current_base].address, 0x2000);
......@@ -216,18 +209,14 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
for (sig = 0; sig < NO_SIGNATURES; ++sig) {
if (check_signature(base + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) {
addr = bases[current_base].address;
#if (DTCDEBUG & DTCDEBUG_INIT)
printk(KERN_DEBUG "scsi-dtc : detected board.\n");
#endif
dprintk(NDEBUG_INIT, "dtc: detected board\n");
goto found;
}
}
iounmap(base);
}
#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
printk(KERN_DEBUG "scsi-dtc : base = %08x\n", addr);
#endif
dprintk(NDEBUG_INIT, "dtc: addr = 0x%08x\n", addr);
if (!addr)
break;
......@@ -235,12 +224,15 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
found:
instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
if (instance == NULL)
break;
goto out_unmap;
instance->base = addr;
((struct NCR5380_hostdata *)(instance)->hostdata)->base = base;
NCR5380_init(instance, 0);
if (NCR5380_init(instance, FLAG_NO_DMA_FIXUP))
goto out_unregister;
NCR5380_maybe_reset_bus(instance);
NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); /* Enable int's */
if (overrides[current_override].irq != IRQ_AUTO)
......@@ -271,14 +263,19 @@ static int __init dtc_detect(struct scsi_host_template * tpnt)
printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no);
instance->irq = NO_IRQ;
#endif
#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
#endif
dprintk(NDEBUG_INIT, "scsi%d : irq = %d\n",
instance->host_no, instance->irq);
++current_override;
++count;
}
return count;
out_unregister:
scsi_unregister(instance);
out_unmap:
iounmap(base);
return count;
}
/*
......@@ -331,12 +328,8 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
unsigned char *d = dst;
int i; /* For counting time spent in the poll-loop */
struct NCR5380_hostdata *hostdata = shost_priv(instance);
NCR5380_local_declare();
NCR5380_setup(instance);
i = 0;
NCR5380_read(RESET_PARITY_INTERRUPT_REG);
NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
if (instance->irq == NO_IRQ)
NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ);
else
......@@ -348,7 +341,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
++i;
rtrc(3);
memcpy_fromio(d, base + DTC_DATA_BUF, 128);
memcpy_fromio(d, hostdata->base + DTC_DATA_BUF, 128);
d += 128;
len -= 128;
rtrc(7);
......@@ -358,9 +351,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
rtrc(4);
while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
++i;
NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
rtrc(0);
NCR5380_read(RESET_PARITY_INTERRUPT_REG);
if (i > hostdata->spin_max_r)
hostdata->spin_max_r = i;
return (0);
......@@ -383,12 +374,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
{
int i;
struct NCR5380_hostdata *hostdata = shost_priv(instance);
NCR5380_local_declare();
NCR5380_setup(instance);
NCR5380_read(RESET_PARITY_INTERRUPT_REG);
NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
/* set direction (write) */
if (instance->irq == NO_IRQ)
NCR5380_write(DTC_CONTROL_REG, 0);
else
......@@ -400,7 +386,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
++i;
rtrc(3);
memcpy_toio(base + DTC_DATA_BUF, src, 128);
memcpy_toio(hostdata->base + DTC_DATA_BUF, src, 128);
src += 128;
len -= 128;
}
......@@ -413,33 +399,44 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
++i;
rtrc(7);
/* Check for parity error here. fixme. */
NCR5380_write(MODE_REG, 0); /* Clear the operating mode */
rtrc(0);
if (i > hostdata->spin_max_w)
hostdata->spin_max_w = i;
return (0);
}
static int dtc_dma_xfer_len(struct scsi_cmnd *cmd)
{
int transfersize = cmd->transfersize;
/* Limit transfers to 32K, for xx400 & xx406
* pseudoDMA that transfers in 128 bytes blocks.
*/
if (transfersize > 32 * 1024 && cmd->SCp.this_residual &&
!(cmd->SCp.this_residual % transfersize))
transfersize = 32 * 1024;
return transfersize;
}
MODULE_LICENSE("GPL");
#include "NCR5380.c"
static int dtc_release(struct Scsi_Host *shost)
{
NCR5380_local_declare();
NCR5380_setup(shost);
struct NCR5380_hostdata *hostdata = shost_priv(shost);
if (shost->irq != NO_IRQ)
free_irq(shost->irq, shost);
NCR5380_exit(shost);
if (shost->io_port && shost->n_io_port)
release_region(shost->io_port, shost->n_io_port);
scsi_unregister(shost);
iounmap(base);
iounmap(hostdata->base);
return 0;
}
static struct scsi_host_template driver_template = {
.name = "DTC 3180/3280 ",
.name = "DTC 3180/3280",
.detect = dtc_detect,
.release = dtc_release,
.proc_name = "dtc3x80",
......@@ -450,10 +447,12 @@ static struct scsi_host_template driver_template = {
.eh_abort_handler = dtc_abort,
.eh_bus_reset_handler = dtc_bus_reset,
.bios_param = dtc_biosparam,
.can_queue = CAN_QUEUE,
.can_queue = 32,
.this_id = 7,
.sg_tablesize = SG_ALL,
.cmd_per_lun = CMD_PER_LUN,
.cmd_per_lun = 2,
.use_clustering = DISABLE_CLUSTERING,
.cmd_size = NCR5380_CMD_SIZE,
.max_sectors = 128,
};
#include "scsi_module.c"
......@@ -10,54 +10,17 @@
#ifndef DTC3280_H
#define DTC3280_H
#define DTCDEBUG 0
#define DTCDEBUG_INIT 0x1
#define DTCDEBUG_TRANSFER 0x2
#ifndef CMD_PER_LUN
#define CMD_PER_LUN 2
#endif
#ifndef CAN_QUEUE
#define CAN_QUEUE 32
#endif
#define NCR5380_implementation_fields \
void __iomem *base
#define NCR5380_local_declare() \
void __iomem *base
#define NCR5380_setup(instance) \
base = ((struct NCR5380_hostdata *)(instance)->hostdata)->base
#define DTC_address(reg) \
(((struct NCR5380_hostdata *)shost_priv(instance))->base + DTC_5380_OFFSET + reg)
#define DTC_address(reg) (base + DTC_5380_OFFSET + reg)
#define dbNCR5380_read(reg) \
(rval=readb(DTC_address(reg)), \
(((unsigned char) printk("DTC : read register %d at addr %p is: %02x\n"\
, (reg), DTC_address(reg), rval)), rval ) )
#define dbNCR5380_write(reg, value) do { \
printk("DTC : write %02x to register %d at address %p\n", \
(value), (reg), DTC_address(reg)); \
writeb(value, DTC_address(reg));} while(0)
#if !(DTCDEBUG & DTCDEBUG_TRANSFER)
#define NCR5380_read(reg) (readb(DTC_address(reg)))
#define NCR5380_write(reg, value) (writeb(value, DTC_address(reg)))
#else
#define NCR5380_read(reg) (readb(DTC_address(reg)))
#define xNCR5380_read(reg) \
(((unsigned char) printk("DTC : read register %d at address %p\n"\
, (reg), DTC_address(reg))), readb(DTC_address(reg)))
#define NCR5380_write(reg, value) do { \
printk("DTC : write %02x to register %d at address %p\n", \
(value), (reg), DTC_address(reg)); \
writeb(value, DTC_address(reg));} while(0)
#endif
#define NCR5380_dma_xfer_len(instance, cmd, phase) \
dtc_dma_xfer_len(cmd)
#define NCR5380_intr dtc_intr
#define NCR5380_queue_command dtc_queue_command
......
......@@ -56,40 +56,31 @@
*
*/
/* settings for DTC3181E card with only Mustek scanner attached */
#define USLEEP_POLL msecs_to_jiffies(10)
#define USLEEP_SLEEP msecs_to_jiffies(200)
#define USLEEP_WAITLONG msecs_to_jiffies(5000)
#define AUTOPROBE_IRQ
#ifdef CONFIG_SCSI_GENERIC_NCR53C400
#define NCR53C400_PSEUDO_DMA 1
#define PSEUDO_DMA
#define NCR53C400
#endif
#include <asm/io.h>
#include <linux/signal.h>
#include <linux/blkdev.h>
#include <linux/module.h>
#include <scsi/scsi_host.h>
#include "g_NCR5380.h"
#include "NCR5380.h"
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/isapnp.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#define NCR_NOT_SET 0
static int ncr_irq = NCR_NOT_SET;
static int ncr_dma = NCR_NOT_SET;
static int ncr_addr = NCR_NOT_SET;
static int ncr_5380 = NCR_NOT_SET;
static int ncr_53c400 = NCR_NOT_SET;
static int ncr_53c400a = NCR_NOT_SET;
static int dtc_3181e = NCR_NOT_SET;
static int ncr_irq;
static int ncr_dma;
static int ncr_addr;
static int ncr_5380;
static int ncr_53c400;
static int ncr_53c400a;
static int dtc_3181e;
static int hp_c2502;
static struct override {
NCR5380_map_type NCR5380_map_name;
......@@ -121,7 +112,7 @@ static struct override {
static void __init internal_setup(int board, char *str, int *ints)
{
static int commandline_current = 0;
static int commandline_current;
switch (board) {
case BOARD_NCR5380:
if (ints[0] != 2 && ints[0] != 3) {
......@@ -235,6 +226,30 @@ static int __init do_DTC3181E_setup(char *str)
#endif
#ifndef SCSI_G_NCR5380_MEM
/*
* Configure I/O address of 53C400A or DTC436 by writing magic numbers
* to ports 0x779 and 0x379.
*/
static void magic_configure(int idx, u8 irq, u8 magic[])
{
u8 cfg = 0;
outb(magic[0], 0x779);
outb(magic[1], 0x379);
outb(magic[2], 0x379);
outb(magic[3], 0x379);
outb(magic[4], 0x379);
/* allowed IRQs for HP C2502 */
if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7)
irq = 0;
if (idx >= 0 && idx <= 7)
cfg = 0x80 | idx | (irq << 4);
outb(cfg, 0x379);
}
#endif
/**
* generic_NCR5380_detect - look for NCR5380 controllers
* @tpnt: the scsi template
......@@ -243,19 +258,18 @@ static int __init do_DTC3181E_setup(char *str)
* and DTC436(ISAPnP) controllers. If overrides have been set we use
* them.
*
* The caller supplied NCR5380_init function is invoked from here, before
* the interrupt line is taken.
*
* Locks: none
*/
static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
{
static int current_override = 0;
static int current_override;
int count;
unsigned int *ports;
u8 *magic = NULL;
#ifndef SCSI_G_NCR5380_MEM
int i;
int port_idx = -1;
unsigned long region_size = 16;
#endif
static unsigned int __initdata ncr_53c400a_ports[] = {
......@@ -264,27 +278,36 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
static unsigned int __initdata dtc_3181e_ports[] = {
0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0
};
int flags = 0;
static u8 ncr_53c400a_magic[] __initdata = { /* 53C400A & DTC436 */
0x59, 0xb9, 0xc5, 0xae, 0xa6
};
static u8 hp_c2502_magic[] __initdata = { /* HP C2502 */
0x0f, 0x22, 0xf0, 0x20, 0x80
};
int flags;
struct Scsi_Host *instance;
struct NCR5380_hostdata *hostdata;
#ifdef SCSI_G_NCR5380_MEM
unsigned long base;
void __iomem *iomem;
#endif
if (ncr_irq != NCR_NOT_SET)
if (ncr_irq)
overrides[0].irq = ncr_irq;
if (ncr_dma != NCR_NOT_SET)
if (ncr_dma)
overrides[0].dma = ncr_dma;
if (ncr_addr != NCR_NOT_SET)
if (ncr_addr)
overrides[0].NCR5380_map_name = (NCR5380_map_type) ncr_addr;
if (ncr_5380 != NCR_NOT_SET)
if (ncr_5380)
overrides[0].board = BOARD_NCR5380;
else if (ncr_53c400 != NCR_NOT_SET)
else if (ncr_53c400)
overrides[0].board = BOARD_NCR53C400;
else if (ncr_53c400a != NCR_NOT_SET)
else if (ncr_53c400a)
overrides[0].board = BOARD_NCR53C400A;
else if (dtc_3181e != NCR_NOT_SET)
else if (dtc_3181e)
overrides[0].board = BOARD_DTC3181E;
else if (hp_c2502)
overrides[0].board = BOARD_HP_C2502;
#ifndef SCSI_G_NCR5380_MEM
if (!current_override && isapnp_present()) {
struct pnp_dev *dev = NULL;
......@@ -318,41 +341,45 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
}
}
#endif
tpnt->proc_name = "g_NCR5380";
for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
if (!(overrides[current_override].NCR5380_map_name))
continue;
ports = NULL;
flags = 0;
switch (overrides[current_override].board) {
case BOARD_NCR5380:
flags = FLAG_NO_PSEUDO_DMA;
break;
case BOARD_NCR53C400:
flags = FLAG_NCR53C400;
#ifdef PSEUDO_DMA
flags = FLAG_NO_DMA_FIXUP;
#endif
break;
case BOARD_NCR53C400A:
flags = FLAG_NO_PSEUDO_DMA;
flags = FLAG_NO_DMA_FIXUP;
ports = ncr_53c400a_ports;
magic = ncr_53c400a_magic;
break;
case BOARD_HP_C2502:
flags = FLAG_NO_DMA_FIXUP;
ports = ncr_53c400a_ports;
magic = hp_c2502_magic;
break;
case BOARD_DTC3181E:
flags = FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E;
flags = FLAG_NO_DMA_FIXUP;
ports = dtc_3181e_ports;
magic = ncr_53c400a_magic;
break;
}
#ifndef SCSI_G_NCR5380_MEM
if (ports) {
if (ports && magic) {
/* wakeup sequence for the NCR53C400A and DTC3181E */
/* Disable the adapter and look for a free io port */
outb(0x59, 0x779);
outb(0xb9, 0x379);
outb(0xc5, 0x379);
outb(0xae, 0x379);
outb(0xa6, 0x379);
outb(0x00, 0x379);
magic_configure(-1, 0, magic);
if (overrides[current_override].NCR5380_map_name != PORT_AUTO)
for (i = 0; ports[i]; i++) {
......@@ -371,17 +398,12 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
}
if (ports[i]) {
/* At this point we have our region reserved */
outb(0x59, 0x779);
outb(0xb9, 0x379);
outb(0xc5, 0x379);
outb(0xae, 0x379);
outb(0xa6, 0x379);
outb(0x80 | i, 0x379); /* set io port to be used */
magic_configure(i, 0, magic); /* no IRQ yet */
outb(0xc0, ports[i] + 9);
if (inb(ports[i] + 9) != 0x80)
continue;
else
overrides[current_override].NCR5380_map_name = ports[i];
port_idx = i;
} else
continue;
}
......@@ -403,24 +425,65 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
}
#endif
instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
if (instance == NULL) {
#ifndef SCSI_G_NCR5380_MEM
release_region(overrides[current_override].NCR5380_map_name, region_size);
#else
iounmap(iomem);
release_mem_region(base, NCR5380_region_size);
#endif
continue;
}
if (instance == NULL)
goto out_release;
hostdata = shost_priv(instance);
instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name;
#ifndef SCSI_G_NCR5380_MEM
instance->io_port = overrides[current_override].NCR5380_map_name;
instance->n_io_port = region_size;
hostdata->io_width = 1; /* 8-bit PDMA by default */
/*
* On NCR53C400 boards, NCR5380 registers are mapped 8 past
* the base address.
*/
switch (overrides[current_override].board) {
case BOARD_NCR53C400:
instance->io_port += 8;
hostdata->c400_ctl_status = 0;
hostdata->c400_blk_cnt = 1;
hostdata->c400_host_buf = 4;
break;
case BOARD_DTC3181E:
hostdata->io_width = 2; /* 16-bit PDMA */
/* fall through */
case BOARD_NCR53C400A:
case BOARD_HP_C2502:
hostdata->c400_ctl_status = 9;
hostdata->c400_blk_cnt = 10;
hostdata->c400_host_buf = 8;
break;
}
#else
((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem;
instance->base = overrides[current_override].NCR5380_map_name;
hostdata->iomem = iomem;
switch (overrides[current_override].board) {
case BOARD_NCR53C400:
hostdata->c400_ctl_status = 0x100;
hostdata->c400_blk_cnt = 0x101;
hostdata->c400_host_buf = 0x104;
break;
case BOARD_DTC3181E:
case BOARD_NCR53C400A:
case BOARD_HP_C2502:
pr_err(DRV_MODULE_NAME ": unknown register offsets\n");
goto out_unregister;
}
#endif
NCR5380_init(instance, flags);
if (NCR5380_init(instance, flags))
goto out_unregister;
switch (overrides[current_override].board) {
case BOARD_NCR53C400:
case BOARD_DTC3181E:
case BOARD_NCR53C400A:
case BOARD_HP_C2502:
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
}
NCR5380_maybe_reset_bus(instance);
if (overrides[current_override].irq != IRQ_AUTO)
instance->irq = overrides[current_override].irq;
......@@ -431,12 +494,18 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
if (instance->irq == 255)
instance->irq = NO_IRQ;
if (instance->irq != NO_IRQ)
if (instance->irq != NO_IRQ) {
#ifndef SCSI_G_NCR5380_MEM
/* set IRQ for HP C2502 */
if (overrides[current_override].board == BOARD_HP_C2502)
magic_configure(port_idx, instance->irq, magic);
#endif
if (request_irq(instance->irq, generic_NCR5380_intr,
0, "NCR5380", instance)) {
printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
instance->irq = NO_IRQ;
}
}
if (instance->irq == NO_IRQ) {
printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
......@@ -447,6 +516,17 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
++count;
}
return count;
out_unregister:
scsi_unregister(instance);
out_release:
#ifndef SCSI_G_NCR5380_MEM
release_region(overrides[current_override].NCR5380_map_name, region_size);
#else
iounmap(iomem);
release_mem_region(base, NCR5380_region_size);
#endif
return count;
}
/**
......@@ -460,21 +540,15 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt)
static int generic_NCR5380_release_resources(struct Scsi_Host *instance)
{
NCR5380_local_declare();
NCR5380_setup(instance);
if (instance->irq != NO_IRQ)
free_irq(instance->irq, instance);
NCR5380_exit(instance);
#ifndef SCSI_G_NCR5380_MEM
release_region(instance->NCR5380_instance_name, instance->n_io_port);
release_region(instance->io_port, instance->n_io_port);
#else
iounmap(((struct NCR5380_hostdata *)instance->hostdata)->iomem);
release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size);
release_mem_region(instance->base, NCR5380_region_size);
#endif
return 0;
}
......@@ -507,7 +581,7 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev,
}
#endif
#ifdef NCR53C400_PSEUDO_DMA
#ifdef PSEUDO_DMA
/**
* NCR5380_pread - pseudo DMA read
......@@ -521,75 +595,68 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev,
static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
{
struct NCR5380_hostdata *hostdata = shost_priv(instance);
int blocks = len / 128;
int start = 0;
int bl;
NCR5380_local_declare();
NCR5380_setup(instance);
NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE | CSR_TRANS_DIR);
NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE | CSR_TRANS_DIR);
NCR5380_write(hostdata->c400_blk_cnt, blocks);
while (1) {
if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
if (NCR5380_read(hostdata->c400_blk_cnt) == 0)
break;
}
if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
printk(KERN_ERR "53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
return -1;
}
while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY);
while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; /* FIXME - no timeout */
#ifndef SCSI_G_NCR5380_MEM
{
int i;
for (i = 0; i < 128; i++)
dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
}
if (hostdata->io_width == 2)
insw(instance->io_port + hostdata->c400_host_buf,
dst + start, 64);
else
insb(instance->io_port + hostdata->c400_host_buf,
dst + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128);
memcpy_fromio(dst + start,
hostdata->iomem + NCR53C400_host_buffer, 128);
#endif
start += 128;
blocks--;
}
if (blocks) {
while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
{
// FIXME - no timeout
}
while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; /* FIXME - no timeout */
#ifndef SCSI_G_NCR5380_MEM
{
int i;
for (i = 0; i < 128; i++)
dst[start + i] = NCR5380_read(C400_HOST_BUFFER);
}
if (hostdata->io_width == 2)
insw(instance->io_port + hostdata->c400_host_buf,
dst + start, 64);
else
insb(instance->io_port + hostdata->c400_host_buf,
dst + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128);
memcpy_fromio(dst + start,
hostdata->iomem + NCR53C400_host_buffer, 128);
#endif
start += 128;
blocks--;
}
if (!(NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ))
printk("53C400r: no 53C80 gated irq after transfer");
#if 0
/*
* DON'T DO THIS - THEY NEVER ARRIVE!
*/
printk("53C400r: Waiting for 53C80 registers\n");
while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG)
/* wait for 53C80 registers to be available */
while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG))
;
#endif
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER))
printk(KERN_ERR "53C400r: no end dma signal\n");
NCR5380_write(MODE_REG, MR_BASE);
NCR5380_read(RESET_PARITY_INTERRUPT_REG);
return 0;
}
......@@ -605,88 +672,90 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst,
static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
{
struct NCR5380_hostdata *hostdata = shost_priv(instance);
int blocks = len / 128;
int start = 0;
int bl;
int i;
NCR5380_local_declare();
NCR5380_setup(instance);
NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE);
NCR5380_write(C400_BLOCK_COUNTER_REG, blocks);
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
NCR5380_write(hostdata->c400_blk_cnt, blocks);
while (1) {
if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) {
if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) {
printk(KERN_ERR "53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks);
return -1;
}
if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) {
if (NCR5380_read(hostdata->c400_blk_cnt) == 0)
break;
}
while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - timeout
#ifndef SCSI_G_NCR5380_MEM
{
for (i = 0; i < 128; i++)
NCR5380_write(C400_HOST_BUFFER, src[start + i]);
}
if (hostdata->io_width == 2)
outsw(instance->io_port + hostdata->c400_host_buf,
src + start, 64);
else
outsb(instance->io_port + hostdata->c400_host_buf,
src + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128);
memcpy_toio(hostdata->iomem + NCR53C400_host_buffer,
src + start, 128);
#endif
start += 128;
blocks--;
}
if (blocks) {
while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
; // FIXME - no timeout
#ifndef SCSI_G_NCR5380_MEM
{
for (i = 0; i < 128; i++)
NCR5380_write(C400_HOST_BUFFER, src[start + i]);
}
if (hostdata->io_width == 2)
outsw(instance->io_port + hostdata->c400_host_buf,
src + start, 64);
else
outsb(instance->io_port + hostdata->c400_host_buf,
src + start, 128);
#else
/* implies SCSI_G_NCR5380_MEM */
memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128);
memcpy_toio(hostdata->iomem + NCR53C400_host_buffer,
src + start, 128);
#endif
start += 128;
blocks--;
}
#if 0
printk("53C400w: waiting for registers to be available\n");
THEY NEVER DO ! while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG);
printk("53C400w: Got em\n");
#endif
/* Let's wait for this instead - could be ugly */
/* All documentation says to check for this. Maybe my hardware is too
* fast. Waiting for it seems to work fine! KLL
*/
while (!(i = NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ))
; // FIXME - no timeout
/*
* I know. i is certainly != 0 here but the loop is new. See previous
* comment.
*/
if (i) {
if (!((i = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_END_DMA_TRANSFER))
printk(KERN_ERR "53C400w: No END OF DMA bit - WHOOPS! BASR=%0x\n", i);
} else
printk(KERN_ERR "53C400w: no 53C80 gated irq after transfer (last block)\n");
/* wait for 53C80 registers to be available */
while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)) {
udelay(4); /* DTC436 chip hangs without this */
/* FIXME - no timeout */
}
#if 0
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) {
printk(KERN_ERR "53C400w: no end dma signal\n");
}
#endif
while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
; // TIMEOUT
return 0;
}
static int generic_NCR5380_dma_xfer_len(struct scsi_cmnd *cmd)
{
int transfersize = cmd->transfersize;
/* Limit transfers to 32K, for xx400 & xx406
* pseudoDMA that transfers in 128 bytes blocks.
*/
if (transfersize > 32 * 1024 && cmd->SCp.this_residual &&
!(cmd->SCp.this_residual % transfersize))
transfersize = 32 * 1024;
/* 53C400 datasheet: non-modulo-128-byte transfers should use PIO */
if (transfersize % 128)
transfersize = 0;
return transfersize;
}
#endif /* PSEUDO_DMA */
/*
......@@ -696,7 +765,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src,
#include "NCR5380.c"
static struct scsi_host_template driver_template = {
.show_info = generic_NCR5380_show_info,
.proc_name = DRV_MODULE_NAME,
.name = "Generic NCR5380/NCR53C400 SCSI",
.detect = generic_NCR5380_detect,
.release = generic_NCR5380_release_resources,
......@@ -705,13 +774,15 @@ static struct scsi_host_template driver_template = {
.eh_abort_handler = generic_NCR5380_abort,
.eh_bus_reset_handler = generic_NCR5380_bus_reset,
.bios_param = NCR5380_BIOSPARAM,
.can_queue = CAN_QUEUE,
.can_queue = 16,
.this_id = 7,
.sg_tablesize = SG_ALL,
.cmd_per_lun = CMD_PER_LUN,
.cmd_per_lun = 2,
.use_clustering = DISABLE_CLUSTERING,
.cmd_size = NCR5380_CMD_SIZE,
.max_sectors = 128,
};
#include <linux/module.h>
#include "scsi_module.c"
module_param(ncr_irq, int, 0);
......@@ -721,6 +792,7 @@ module_param(ncr_5380, int, 0);
module_param(ncr_53c400, int, 0);
module_param(ncr_53c400a, int, 0);
module_param(dtc_3181e, int, 0);
module_param(hp_c2502, int, 0);
MODULE_LICENSE("GPL");
#if !defined(SCSI_G_NCR5380_MEM) && defined(MODULE)
......
......@@ -14,81 +14,67 @@
#ifndef GENERIC_NCR5380_H
#define GENERIC_NCR5380_H
#ifdef NCR53C400
#ifdef CONFIG_SCSI_GENERIC_NCR53C400
#define BIOSPARAM
#define NCR5380_BIOSPARAM generic_NCR5380_biosparam
#else
#define NCR5380_BIOSPARAM NULL
#endif
#ifndef ASM
#ifndef CMD_PER_LUN
#define CMD_PER_LUN 2
#endif
#ifndef CAN_QUEUE
#define CAN_QUEUE 16
#endif
#define __STRVAL(x) #x
#define STRVAL(x) __STRVAL(x)
#ifndef SCSI_G_NCR5380_MEM
#define DRV_MODULE_NAME "g_NCR5380"
#define NCR5380_map_config port
#define NCR5380_map_type int
#define NCR5380_map_name port
#define NCR5380_instance_name io_port
#define NCR53C400_register_offset 0
#define NCR53C400_address_adjust 8
#ifdef NCR53C400
#ifdef CONFIG_SCSI_GENERIC_NCR53C400
#define NCR5380_region_size 16
#else
#define NCR5380_region_size 8
#endif
#define NCR5380_read(reg) (inb(NCR5380_map_name + (reg)))
#define NCR5380_write(reg, value) (outb((value), (NCR5380_map_name + (reg))))
#define NCR5380_read(reg) \
inb(instance->io_port + (reg))
#define NCR5380_write(reg, value) \
outb(value, instance->io_port + (reg))
#define NCR5380_implementation_fields \
NCR5380_map_type NCR5380_map_name
#define NCR5380_local_declare() \
register NCR5380_implementation_fields
#define NCR5380_setup(instance) \
NCR5380_map_name = (NCR5380_map_type)((instance)->NCR5380_instance_name)
int c400_ctl_status; \
int c400_blk_cnt; \
int c400_host_buf; \
int io_width;
#else
/* therefore SCSI_G_NCR5380_MEM */
#define DRV_MODULE_NAME "g_NCR5380_mmio"
#define NCR5380_map_config memory
#define NCR5380_map_type unsigned long
#define NCR5380_map_name base
#define NCR5380_instance_name base
#define NCR53C400_register_offset 0x108
#define NCR53C400_address_adjust 0
#define NCR53C400_mem_base 0x3880
#define NCR53C400_host_buffer 0x3900
#define NCR5380_region_size 0x3a00
#define NCR5380_read(reg) readb(iomem + NCR53C400_mem_base + (reg))
#define NCR5380_write(reg, value) writeb(value, iomem + NCR53C400_mem_base + (reg))
#define NCR5380_read(reg) \
readb(((struct NCR5380_hostdata *)shost_priv(instance))->iomem + \
NCR53C400_mem_base + (reg))
#define NCR5380_write(reg, value) \
writeb(value, ((struct NCR5380_hostdata *)shost_priv(instance))->iomem + \
NCR53C400_mem_base + (reg))
#define NCR5380_implementation_fields \
NCR5380_map_type NCR5380_map_name; \
void __iomem *iomem;
#define NCR5380_local_declare() \
register void __iomem *iomem
#define NCR5380_setup(instance) \
iomem = (((struct NCR5380_hostdata *)(instance)->hostdata)->iomem)
void __iomem *iomem; \
int c400_ctl_status; \
int c400_blk_cnt; \
int c400_host_buf;
#endif
#define NCR5380_dma_xfer_len(instance, cmd, phase) \
generic_NCR5380_dma_xfer_len(cmd)
#define NCR5380_intr generic_NCR5380_intr
#define NCR5380_queue_command generic_NCR5380_queue_command
#define NCR5380_abort generic_NCR5380_abort
......@@ -102,7 +88,7 @@
#define BOARD_NCR53C400 1
#define BOARD_NCR53C400A 2
#define BOARD_DTC3181E 3
#define BOARD_HP_C2502 4
#endif /* ndef ASM */
#endif /* GENERIC_NCR5380_H */
......@@ -247,41 +247,36 @@
/* ITCT header */
/* qw0 */
#define ITCT_HDR_DEV_TYPE_OFF 0
#define ITCT_HDR_DEV_TYPE_MSK (0x3 << ITCT_HDR_DEV_TYPE_OFF)
#define ITCT_HDR_DEV_TYPE_MSK (0x3ULL << ITCT_HDR_DEV_TYPE_OFF)
#define ITCT_HDR_VALID_OFF 2
#define ITCT_HDR_VALID_MSK (0x1 << ITCT_HDR_VALID_OFF)
#define ITCT_HDR_BREAK_REPLY_ENA_OFF 3
#define ITCT_HDR_BREAK_REPLY_ENA_MSK (0x1 << ITCT_HDR_BREAK_REPLY_ENA_OFF)
#define ITCT_HDR_VALID_MSK (0x1ULL << ITCT_HDR_VALID_OFF)
#define ITCT_HDR_AWT_CONTROL_OFF 4
#define ITCT_HDR_AWT_CONTROL_MSK (0x1 << ITCT_HDR_AWT_CONTROL_OFF)
#define ITCT_HDR_AWT_CONTROL_MSK (0x1ULL << ITCT_HDR_AWT_CONTROL_OFF)
#define ITCT_HDR_MAX_CONN_RATE_OFF 5
#define ITCT_HDR_MAX_CONN_RATE_MSK (0xf << ITCT_HDR_MAX_CONN_RATE_OFF)
#define ITCT_HDR_MAX_CONN_RATE_MSK (0xfULL << ITCT_HDR_MAX_CONN_RATE_OFF)
#define ITCT_HDR_VALID_LINK_NUM_OFF 9
#define ITCT_HDR_VALID_LINK_NUM_MSK (0xf << ITCT_HDR_VALID_LINK_NUM_OFF)
#define ITCT_HDR_VALID_LINK_NUM_MSK (0xfULL << ITCT_HDR_VALID_LINK_NUM_OFF)
#define ITCT_HDR_PORT_ID_OFF 13
#define ITCT_HDR_PORT_ID_MSK (0x7 << ITCT_HDR_PORT_ID_OFF)
#define ITCT_HDR_PORT_ID_MSK (0x7ULL << ITCT_HDR_PORT_ID_OFF)
#define ITCT_HDR_SMP_TIMEOUT_OFF 16
#define ITCT_HDR_SMP_TIMEOUT_MSK (0xffff << ITCT_HDR_SMP_TIMEOUT_OFF)
#define ITCT_HDR_MAX_BURST_BYTES_OFF 16
#define ITCT_HDR_MAX_BURST_BYTES_MSK (0xffffffff << \
ITCT_MAX_BURST_BYTES_OFF)
#define ITCT_HDR_SMP_TIMEOUT_MSK (0xffffULL << ITCT_HDR_SMP_TIMEOUT_OFF)
/* qw1 */
#define ITCT_HDR_MAX_SAS_ADDR_OFF 0
#define ITCT_HDR_MAX_SAS_ADDR_MSK (0xffffffffffffffff << \
ITCT_HDR_MAX_SAS_ADDR_OFF)
/* qw2 */
#define ITCT_HDR_IT_NEXUS_LOSS_TL_OFF 0
#define ITCT_HDR_IT_NEXUS_LOSS_TL_MSK (0xffff << \
#define ITCT_HDR_IT_NEXUS_LOSS_TL_MSK (0xffffULL << \
ITCT_HDR_IT_NEXUS_LOSS_TL_OFF)
#define ITCT_HDR_BUS_INACTIVE_TL_OFF 16
#define ITCT_HDR_BUS_INACTIVE_TL_MSK (0xffff << \
#define ITCT_HDR_BUS_INACTIVE_TL_MSK (0xffffULL << \
ITCT_HDR_BUS_INACTIVE_TL_OFF)
#define ITCT_HDR_MAX_CONN_TL_OFF 32
#define ITCT_HDR_MAX_CONN_TL_MSK (0xffff << \
#define ITCT_HDR_MAX_CONN_TL_MSK (0xffffULL << \
ITCT_HDR_MAX_CONN_TL_OFF)
#define ITCT_HDR_REJ_OPEN_TL_OFF 48
#define ITCT_HDR_REJ_OPEN_TL_MSK (0xffff << \
ITCT_REJ_OPEN_TL_OFF)
#define ITCT_HDR_REJ_OPEN_TL_MSK (0xffffULL << \
ITCT_HDR_REJ_OPEN_TL_OFF)
/* Err record header */
#define ERR_HDR_DMA_TX_ERR_TYPE_OFF 0
......@@ -533,10 +528,10 @@ static void setup_itct_v1_hw(struct hisi_hba *hisi_hba,
itct->sas_addr = __swab64(itct->sas_addr);
/* qw2 */
itct->qw2 = cpu_to_le64((500 < ITCT_HDR_IT_NEXUS_LOSS_TL_OFF) |
(0xff00 < ITCT_HDR_BUS_INACTIVE_TL_OFF) |
(0xff00 < ITCT_HDR_MAX_CONN_TL_OFF) |
(0xff00 < ITCT_HDR_REJ_OPEN_TL_OFF));
itct->qw2 = cpu_to_le64((500ULL << ITCT_HDR_IT_NEXUS_LOSS_TL_OFF) |
(0xff00ULL << ITCT_HDR_BUS_INACTIVE_TL_OFF) |
(0xff00ULL << ITCT_HDR_MAX_CONN_TL_OFF) |
(0xff00ULL << ITCT_HDR_REJ_OPEN_TL_OFF));
}
static void free_device_v1_hw(struct hisi_hba *hisi_hba,
......@@ -544,7 +539,8 @@ static void free_device_v1_hw(struct hisi_hba *hisi_hba,
{
u64 dev_id = sas_dev->device_id;
struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
u32 qw0, reg_val = hisi_sas_read32(hisi_hba, CFG_AGING_TIME);
u64 qw0;
u32 reg_val = hisi_sas_read32(hisi_hba, CFG_AGING_TIME);
reg_val |= CFG_AGING_TIME_ITCT_REL_MSK;
hisi_sas_write32(hisi_hba, CFG_AGING_TIME, reg_val);
......
......@@ -43,6 +43,7 @@ typedef struct {
unsigned dp:1; /* Data phase present */
unsigned rd:1; /* Read data in data phase */
unsigned wanted:1; /* Parport sharing busy flag */
unsigned int dev_no; /* Device number */
wait_queue_head_t *waiting;
struct Scsi_Host *host;
struct list_head list;
......@@ -1120,15 +1121,40 @@ static struct scsi_host_template imm_template = {
static LIST_HEAD(imm_hosts);
/*
* Finds the first available device number that can be alloted to the
* new imm device and returns the address of the previous node so that
* we can add to the tail and have a list in the ascending order.
*/
static inline imm_struct *find_parent(void)
{
imm_struct *dev, *par = NULL;
unsigned int cnt = 0;
if (list_empty(&imm_hosts))
return NULL;
list_for_each_entry(dev, &imm_hosts, list) {
if (dev->dev_no != cnt)
return par;
cnt++;
par = dev;
}
return par;
}
static int __imm_attach(struct parport *pb)
{
struct Scsi_Host *host;
imm_struct *dev;
imm_struct *dev, *temp;
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waiting);
DEFINE_WAIT(wait);
int ports;
int modes, ppb;
int err = -ENOMEM;
struct pardev_cb imm_cb;
init_waitqueue_head(&waiting);
......@@ -1141,9 +1167,15 @@ static int __imm_attach(struct parport *pb)
dev->mode = IMM_AUTODETECT;
INIT_LIST_HEAD(&dev->list);
dev->dev = parport_register_device(pb, "imm", NULL, imm_wakeup,
NULL, 0, dev);
temp = find_parent();
if (temp)
dev->dev_no = temp->dev_no + 1;
memset(&imm_cb, 0, sizeof(imm_cb));
imm_cb.private = dev;
imm_cb.wakeup = imm_wakeup;
dev->dev = parport_register_dev_model(pb, "imm", &imm_cb, dev->dev_no);
if (!dev->dev)
goto out;
......@@ -1207,7 +1239,10 @@ static int __imm_attach(struct parport *pb)
host->unique_id = pb->number;
*(imm_struct **)&host->hostdata = dev;
dev->host = host;
if (!temp)
list_add_tail(&dev->list, &imm_hosts);
else
list_add_tail(&dev->list, &temp->list);
err = scsi_add_host(host, NULL);
if (err)
goto out2;
......@@ -1246,8 +1281,9 @@ static void imm_detach(struct parport *pb)
static struct parport_driver imm_driver = {
.name = "imm",
.attach = imm_attach,
.match_port = imm_attach,
.detach = imm_detach,
.devmodel = true,
};
static int __init imm_driver_init(void)
......
......@@ -4003,13 +4003,12 @@ static ssize_t ipr_store_update_fw(struct device *dev,
struct ipr_sglist *sglist;
char fname[100];
char *src;
int len, result, dnld_size;
int result, dnld_size;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
len = snprintf(fname, 99, "%s", buf);
fname[len-1] = '\0';
snprintf(fname, sizeof(fname), "%s", buf);
if (request_firmware(&fw_entry, fname, &ioa_cfg->pdev->dev)) {
dev_err(&ioa_cfg->pdev->dev, "Firmware file %s not found\n", fname);
......
此差异已折叠。
......@@ -179,8 +179,12 @@ mraid_mm_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
/*
* The following call will block till a kioc is available
* or return NULL if the list head is empty for the pointer
* of type mraid_mmapt passed to mraid_mm_alloc_kioc
*/
kioc = mraid_mm_alloc_kioc(adp);
if (!kioc)
return -ENXIO;
/*
* User sent the old mimd_t ioctl packet. Convert it to uioc_t.
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册