Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
This commit is contained in:
82
drivers/scsi/pcmcia/Kconfig
Normal file
82
drivers/scsi/pcmcia/Kconfig
Normal file
@@ -0,0 +1,82 @@
|
||||
#
|
||||
# PCMCIA SCSI adapter configuration
|
||||
#
|
||||
|
||||
menu "PCMCIA SCSI adapter support"
|
||||
depends on SCSI!=n && PCMCIA!=n && MODULES
|
||||
|
||||
config PCMCIA_AHA152X
|
||||
tristate "Adaptec AHA152X PCMCIA support"
|
||||
depends on m && !64BIT
|
||||
help
|
||||
Say Y here if you intend to attach this type of PCMCIA SCSI host
|
||||
adapter to your computer.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called aha152x_cs.
|
||||
|
||||
config PCMCIA_FDOMAIN
|
||||
tristate "Future Domain PCMCIA support"
|
||||
depends on m
|
||||
help
|
||||
Say Y here if you intend to attach this type of PCMCIA SCSI host
|
||||
adapter to your computer.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called fdomain_cs.
|
||||
|
||||
config PCMCIA_NINJA_SCSI
|
||||
tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support"
|
||||
depends on m && !64BIT
|
||||
help
|
||||
If you intend to attach this type of PCMCIA SCSI host adapter to
|
||||
your computer, say Y here and read
|
||||
<file:Documentation/scsi/NinjaSCSI.txt>.
|
||||
|
||||
Supported cards:
|
||||
|
||||
NinjaSCSI-3: (version string: "WBT","NinjaSCSI-3","R1.0")
|
||||
IO-DATA PCSC-FP
|
||||
ALPHA DATA AD-PCS201
|
||||
CyQ've SFC-201
|
||||
LOGITECH LPM-SCSI2E
|
||||
Pioneer PCR-PR24's card
|
||||
I-O DATA CDPS-PX24's card (PCSC-F)
|
||||
Panasonic KXL-RW10AN CD-RW's card
|
||||
etc.
|
||||
|
||||
NinjaSCSI-32Bit (in 16bit mode):
|
||||
[Workbit (version string: "WORKBIT","UltraNinja-16","1")]
|
||||
Jazz SCP050
|
||||
[I-O DATA (OEM) (version string: "IO DATA","CBSC16 ","1")]
|
||||
I-O DATA CBSC-II
|
||||
[Kyusyu Matsushita Kotobuki (OEM)
|
||||
(version string: "KME ","SCSI-CARD-001","1")]
|
||||
KME KXL-820AN's card
|
||||
HP M820e CDRW's card
|
||||
etc.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called nsp_cs.
|
||||
|
||||
config PCMCIA_QLOGIC
|
||||
tristate "Qlogic PCMCIA support"
|
||||
depends on m
|
||||
help
|
||||
Say Y here if you intend to attach this type of PCMCIA SCSI host
|
||||
adapter to your computer.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called qlogic_cs.
|
||||
|
||||
config PCMCIA_SYM53C500
|
||||
tristate "Symbios 53c500 PCMCIA support"
|
||||
depends on m
|
||||
help
|
||||
Say Y here if you have a New Media Bus Toaster or other PCMCIA
|
||||
SCSI adapter based on the Symbios 53c500 controller.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called sym53c500_cs.
|
||||
|
||||
endmenu
|
||||
13
drivers/scsi/pcmcia/Makefile
Normal file
13
drivers/scsi/pcmcia/Makefile
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
EXTRA_CFLAGS += -Idrivers/scsi
|
||||
|
||||
# 16-bit client drivers
|
||||
obj-$(CONFIG_PCMCIA_QLOGIC) += qlogic_cs.o
|
||||
obj-$(CONFIG_PCMCIA_FDOMAIN) += fdomain_cs.o
|
||||
obj-$(CONFIG_PCMCIA_AHA152X) += aha152x_cs.o
|
||||
obj-$(CONFIG_PCMCIA_NINJA_SCSI) += nsp_cs.o
|
||||
obj-$(CONFIG_PCMCIA_SYM53C500) += sym53c500_cs.o
|
||||
|
||||
aha152x_cs-objs := aha152x_stub.o aha152x_core.o
|
||||
fdomain_cs-objs := fdomain_stub.o fdomain_core.o
|
||||
qlogic_cs-objs := qlogic_stub.o
|
||||
3
drivers/scsi/pcmcia/aha152x_core.c
Normal file
3
drivers/scsi/pcmcia/aha152x_core.c
Normal file
@@ -0,0 +1,3 @@
|
||||
#define PCMCIA 1
|
||||
#define AHA152X_STAT 1
|
||||
#include "aha152x.c"
|
||||
343
drivers/scsi/pcmcia/aha152x_stub.c
Normal file
343
drivers/scsi/pcmcia/aha152x_stub.c
Normal file
@@ -0,0 +1,343 @@
|
||||
/*======================================================================
|
||||
|
||||
A driver for Adaptec AHA152X-compatible PCMCIA SCSI cards.
|
||||
|
||||
This driver supports the Adaptec AHA-1460, the New Media Bus
|
||||
Toaster, and the New Media Toast & Jam.
|
||||
|
||||
aha152x_cs.c 1.54 2000/06/12 21:27:25
|
||||
|
||||
The contents of this file are subject to the Mozilla Public
|
||||
License Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License. You may obtain a copy of
|
||||
the License at http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS
|
||||
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
rights and limitations under the License.
|
||||
|
||||
The initial developer of the original code is David A. Hinds
|
||||
<dahinds@users.sourceforge.net>. Portions created by David A. Hinds
|
||||
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
|
||||
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
|
||||
by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this
|
||||
file under either the MPL or the GPL.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <scsi/scsi_ioctl.h>
|
||||
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
#include "aha152x.h"
|
||||
|
||||
#include <pcmcia/version.h>
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ds.h>
|
||||
|
||||
#ifdef PCMCIA_DEBUG
|
||||
static int pc_debug = PCMCIA_DEBUG;
|
||||
module_param(pc_debug, int, 0644);
|
||||
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
|
||||
static char *version =
|
||||
"aha152x_cs.c 1.54 2000/06/12 21:27:25 (David Hinds)";
|
||||
#else
|
||||
#define DEBUG(n, args...)
|
||||
#endif
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
/* Parameters that can be set with 'insmod' */
|
||||
|
||||
/* SCSI bus setup options */
|
||||
static int host_id = 7;
|
||||
static int reconnect = 1;
|
||||
static int parity = 1;
|
||||
static int synchronous = 1;
|
||||
static int reset_delay = 100;
|
||||
static int ext_trans = 0;
|
||||
|
||||
module_param(host_id, int, 0);
|
||||
module_param(reconnect, int, 0);
|
||||
module_param(parity, int, 0);
|
||||
module_param(synchronous, int, 0);
|
||||
module_param(reset_delay, int, 0);
|
||||
module_param(ext_trans, int, 0);
|
||||
|
||||
MODULE_LICENSE("Dual MPL/GPL");
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
typedef struct scsi_info_t {
|
||||
dev_link_t link;
|
||||
dev_node_t node;
|
||||
struct Scsi_Host *host;
|
||||
} scsi_info_t;
|
||||
|
||||
static void aha152x_release_cs(dev_link_t *link);
|
||||
static int aha152x_event(event_t event, int priority,
|
||||
event_callback_args_t *args);
|
||||
|
||||
static dev_link_t *aha152x_attach(void);
|
||||
static void aha152x_detach(dev_link_t *);
|
||||
|
||||
static dev_link_t *dev_list;
|
||||
static dev_info_t dev_info = "aha152x_cs";
|
||||
|
||||
static dev_link_t *aha152x_attach(void)
|
||||
{
|
||||
scsi_info_t *info;
|
||||
client_reg_t client_reg;
|
||||
dev_link_t *link;
|
||||
int ret;
|
||||
|
||||
DEBUG(0, "aha152x_attach()\n");
|
||||
|
||||
/* Create new SCSI device */
|
||||
info = kmalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info) return NULL;
|
||||
memset(info, 0, sizeof(*info));
|
||||
link = &info->link; link->priv = info;
|
||||
|
||||
link->io.NumPorts1 = 0x20;
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
|
||||
link->io.IOAddrLines = 10;
|
||||
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
|
||||
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
|
||||
link->conf.Attributes = CONF_ENABLE_IRQ;
|
||||
link->conf.Vcc = 50;
|
||||
link->conf.IntType = INT_MEMORY_AND_IO;
|
||||
link->conf.Present = PRESENT_OPTION;
|
||||
|
||||
/* Register with Card Services */
|
||||
link->next = dev_list;
|
||||
dev_list = link;
|
||||
client_reg.dev_info = &dev_info;
|
||||
client_reg.event_handler = &aha152x_event;
|
||||
client_reg.EventMask =
|
||||
CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
|
||||
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
|
||||
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
|
||||
client_reg.Version = 0x0210;
|
||||
client_reg.event_callback_args.client_data = link;
|
||||
ret = pcmcia_register_client(&link->handle, &client_reg);
|
||||
if (ret != 0) {
|
||||
cs_error(link->handle, RegisterClient, ret);
|
||||
aha152x_detach(link);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return link;
|
||||
} /* aha152x_attach */
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static void aha152x_detach(dev_link_t *link)
|
||||
{
|
||||
dev_link_t **linkp;
|
||||
|
||||
DEBUG(0, "aha152x_detach(0x%p)\n", link);
|
||||
|
||||
/* Locate device structure */
|
||||
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
|
||||
if (*linkp == link) break;
|
||||
if (*linkp == NULL)
|
||||
return;
|
||||
|
||||
if (link->state & DEV_CONFIG)
|
||||
aha152x_release_cs(link);
|
||||
|
||||
if (link->handle)
|
||||
pcmcia_deregister_client(link->handle);
|
||||
|
||||
/* Unlink device structure, free bits */
|
||||
*linkp = link->next;
|
||||
kfree(link->priv);
|
||||
|
||||
} /* aha152x_detach */
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
#define CS_CHECK(fn, ret) \
|
||||
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
|
||||
|
||||
static void aha152x_config_cs(dev_link_t *link)
|
||||
{
|
||||
client_handle_t handle = link->handle;
|
||||
scsi_info_t *info = link->priv;
|
||||
struct aha152x_setup s;
|
||||
tuple_t tuple;
|
||||
cisparse_t parse;
|
||||
int i, last_ret, last_fn;
|
||||
u_char tuple_data[64];
|
||||
struct Scsi_Host *host;
|
||||
|
||||
DEBUG(0, "aha152x_config(0x%p)\n", link);
|
||||
|
||||
tuple.DesiredTuple = CISTPL_CONFIG;
|
||||
tuple.TupleData = tuple_data;
|
||||
tuple.TupleDataMax = 64;
|
||||
tuple.TupleOffset = 0;
|
||||
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
|
||||
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
|
||||
CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
|
||||
link->conf.ConfigBase = parse.config.base;
|
||||
|
||||
/* Configure card */
|
||||
link->state |= DEV_CONFIG;
|
||||
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
|
||||
while (1) {
|
||||
if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
|
||||
pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
|
||||
goto next_entry;
|
||||
/* For New Media T&J, look for a SCSI window */
|
||||
if (parse.cftable_entry.io.win[0].len >= 0x20)
|
||||
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
|
||||
else if ((parse.cftable_entry.io.nwin > 1) &&
|
||||
(parse.cftable_entry.io.win[1].len >= 0x20))
|
||||
link->io.BasePort1 = parse.cftable_entry.io.win[1].base;
|
||||
if ((parse.cftable_entry.io.nwin > 0) &&
|
||||
(link->io.BasePort1 < 0xffff)) {
|
||||
link->conf.ConfigIndex = parse.cftable_entry.index;
|
||||
i = pcmcia_request_io(handle, &link->io);
|
||||
if (i == CS_SUCCESS) break;
|
||||
}
|
||||
next_entry:
|
||||
CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
|
||||
}
|
||||
|
||||
CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
|
||||
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
|
||||
|
||||
/* Set configuration options for the aha152x driver */
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.conf = "PCMCIA setup";
|
||||
s.io_port = link->io.BasePort1;
|
||||
s.irq = link->irq.AssignedIRQ;
|
||||
s.scsiid = host_id;
|
||||
s.reconnect = reconnect;
|
||||
s.parity = parity;
|
||||
s.synchronous = synchronous;
|
||||
s.delay = reset_delay;
|
||||
if (ext_trans)
|
||||
s.ext_trans = ext_trans;
|
||||
|
||||
host = aha152x_probe_one(&s);
|
||||
if (host == NULL) {
|
||||
printk(KERN_INFO "aha152x_cs: no SCSI devices found\n");
|
||||
goto cs_failed;
|
||||
}
|
||||
|
||||
sprintf(info->node.dev_name, "scsi%d", host->host_no);
|
||||
link->dev = &info->node;
|
||||
info->host = host;
|
||||
|
||||
link->state &= ~DEV_CONFIG_PENDING;
|
||||
return;
|
||||
|
||||
cs_failed:
|
||||
cs_error(link->handle, last_fn, last_ret);
|
||||
aha152x_release_cs(link);
|
||||
return;
|
||||
}
|
||||
|
||||
static void aha152x_release_cs(dev_link_t *link)
|
||||
{
|
||||
scsi_info_t *info = link->priv;
|
||||
|
||||
aha152x_release(info->host);
|
||||
link->dev = NULL;
|
||||
|
||||
pcmcia_release_configuration(link->handle);
|
||||
pcmcia_release_io(link->handle, &link->io);
|
||||
pcmcia_release_irq(link->handle, &link->irq);
|
||||
|
||||
link->state &= ~DEV_CONFIG;
|
||||
}
|
||||
|
||||
static int aha152x_event(event_t event, int priority,
|
||||
event_callback_args_t *args)
|
||||
{
|
||||
dev_link_t *link = args->client_data;
|
||||
scsi_info_t *info = link->priv;
|
||||
|
||||
DEBUG(0, "aha152x_event(0x%06x)\n", event);
|
||||
|
||||
switch (event) {
|
||||
case CS_EVENT_CARD_REMOVAL:
|
||||
link->state &= ~DEV_PRESENT;
|
||||
if (link->state & DEV_CONFIG)
|
||||
aha152x_release_cs(link);
|
||||
break;
|
||||
case CS_EVENT_CARD_INSERTION:
|
||||
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
|
||||
aha152x_config_cs(link);
|
||||
break;
|
||||
case CS_EVENT_PM_SUSPEND:
|
||||
link->state |= DEV_SUSPEND;
|
||||
/* Fall through... */
|
||||
case CS_EVENT_RESET_PHYSICAL:
|
||||
if (link->state & DEV_CONFIG)
|
||||
pcmcia_release_configuration(link->handle);
|
||||
break;
|
||||
case CS_EVENT_PM_RESUME:
|
||||
link->state &= ~DEV_SUSPEND;
|
||||
/* Fall through... */
|
||||
case CS_EVENT_CARD_RESET:
|
||||
if (link->state & DEV_CONFIG) {
|
||||
Scsi_Cmnd tmp;
|
||||
pcmcia_request_configuration(link->handle, &link->conf);
|
||||
tmp.device->host = info->host;
|
||||
aha152x_host_reset(&tmp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pcmcia_driver aha152x_cs_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.drv = {
|
||||
.name = "aha152x_cs",
|
||||
},
|
||||
.attach = aha152x_attach,
|
||||
.detach = aha152x_detach,
|
||||
};
|
||||
|
||||
static int __init init_aha152x_cs(void)
|
||||
{
|
||||
return pcmcia_register_driver(&aha152x_cs_driver);
|
||||
}
|
||||
|
||||
static void __exit exit_aha152x_cs(void)
|
||||
{
|
||||
pcmcia_unregister_driver(&aha152x_cs_driver);
|
||||
BUG_ON(dev_list != NULL);
|
||||
}
|
||||
|
||||
module_init(init_aha152x_cs);
|
||||
module_exit(exit_aha152x_cs);
|
||||
|
||||
2
drivers/scsi/pcmcia/fdomain_core.c
Normal file
2
drivers/scsi/pcmcia/fdomain_core.c
Normal file
@@ -0,0 +1,2 @@
|
||||
#define PCMCIA 1
|
||||
#include "fdomain.c"
|
||||
323
drivers/scsi/pcmcia/fdomain_stub.c
Normal file
323
drivers/scsi/pcmcia/fdomain_stub.c
Normal file
@@ -0,0 +1,323 @@
|
||||
/*======================================================================
|
||||
|
||||
A driver for Future Domain-compatible PCMCIA SCSI cards
|
||||
|
||||
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
|
||||
except in compliance with the License. You may obtain a copy of
|
||||
the License at http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS
|
||||
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
rights and limitations under the License.
|
||||
|
||||
The initial developer of the original code is David A. Hinds
|
||||
<dahinds@users.sourceforge.net>. Portions created by David A. Hinds
|
||||
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
|
||||
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
|
||||
by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this
|
||||
file under either the MPL or the GPL.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <scsi/scsi_ioctl.h>
|
||||
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
#include "fdomain.h"
|
||||
|
||||
#include <pcmcia/version.h>
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ds.h>
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
/* Module parameters */
|
||||
|
||||
MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
|
||||
MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver");
|
||||
MODULE_LICENSE("Dual MPL/GPL");
|
||||
|
||||
#ifdef PCMCIA_DEBUG
|
||||
static int pc_debug = PCMCIA_DEBUG;
|
||||
module_param(pc_debug, int, 0);
|
||||
#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 {
|
||||
dev_link_t link;
|
||||
dev_node_t node;
|
||||
struct Scsi_Host *host;
|
||||
} scsi_info_t;
|
||||
|
||||
|
||||
static void fdomain_release(dev_link_t *link);
|
||||
static int fdomain_event(event_t event, int priority,
|
||||
event_callback_args_t *args);
|
||||
|
||||
static dev_link_t *fdomain_attach(void);
|
||||
static void fdomain_detach(dev_link_t *);
|
||||
|
||||
|
||||
static dev_link_t *dev_list = NULL;
|
||||
|
||||
static dev_info_t dev_info = "fdomain_cs";
|
||||
|
||||
static dev_link_t *fdomain_attach(void)
|
||||
{
|
||||
scsi_info_t *info;
|
||||
client_reg_t client_reg;
|
||||
dev_link_t *link;
|
||||
int ret;
|
||||
|
||||
DEBUG(0, "fdomain_attach()\n");
|
||||
|
||||
/* Create new SCSI device */
|
||||
info = kmalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info) return NULL;
|
||||
memset(info, 0, sizeof(*info));
|
||||
link = &info->link; link->priv = info;
|
||||
link->io.NumPorts1 = 0x10;
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
|
||||
link->io.IOAddrLines = 10;
|
||||
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
|
||||
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
|
||||
link->conf.Attributes = CONF_ENABLE_IRQ;
|
||||
link->conf.Vcc = 50;
|
||||
link->conf.IntType = INT_MEMORY_AND_IO;
|
||||
link->conf.Present = PRESENT_OPTION;
|
||||
|
||||
/* Register with Card Services */
|
||||
link->next = dev_list;
|
||||
dev_list = link;
|
||||
client_reg.dev_info = &dev_info;
|
||||
client_reg.event_handler = &fdomain_event;
|
||||
client_reg.EventMask =
|
||||
CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
|
||||
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
|
||||
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
|
||||
client_reg.Version = 0x0210;
|
||||
client_reg.event_callback_args.client_data = link;
|
||||
ret = pcmcia_register_client(&link->handle, &client_reg);
|
||||
if (ret != 0) {
|
||||
cs_error(link->handle, RegisterClient, ret);
|
||||
fdomain_detach(link);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return link;
|
||||
} /* fdomain_attach */
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static void fdomain_detach(dev_link_t *link)
|
||||
{
|
||||
dev_link_t **linkp;
|
||||
|
||||
DEBUG(0, "fdomain_detach(0x%p)\n", link);
|
||||
|
||||
/* Locate device structure */
|
||||
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
|
||||
if (*linkp == link) break;
|
||||
if (*linkp == NULL)
|
||||
return;
|
||||
|
||||
if (link->state & DEV_CONFIG)
|
||||
fdomain_release(link);
|
||||
|
||||
if (link->handle)
|
||||
pcmcia_deregister_client(link->handle);
|
||||
|
||||
/* Unlink device structure, free bits */
|
||||
*linkp = link->next;
|
||||
kfree(link->priv);
|
||||
|
||||
} /* fdomain_detach */
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
#define CS_CHECK(fn, ret) \
|
||||
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
|
||||
|
||||
static void fdomain_config(dev_link_t *link)
|
||||
{
|
||||
client_handle_t handle = link->handle;
|
||||
scsi_info_t *info = link->priv;
|
||||
tuple_t tuple;
|
||||
cisparse_t parse;
|
||||
int i, last_ret, last_fn;
|
||||
u_char tuple_data[64];
|
||||
char str[16];
|
||||
struct Scsi_Host *host;
|
||||
|
||||
DEBUG(0, "fdomain_config(0x%p)\n", link);
|
||||
|
||||
tuple.DesiredTuple = CISTPL_CONFIG;
|
||||
tuple.TupleData = tuple_data;
|
||||
tuple.TupleDataMax = 64;
|
||||
tuple.TupleOffset = 0;
|
||||
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
|
||||
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
|
||||
CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
|
||||
link->conf.ConfigBase = parse.config.base;
|
||||
|
||||
/* Configure card */
|
||||
link->state |= DEV_CONFIG;
|
||||
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
|
||||
while (1) {
|
||||
if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
|
||||
pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
|
||||
goto next_entry;
|
||||
link->conf.ConfigIndex = parse.cftable_entry.index;
|
||||
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
|
||||
i = pcmcia_request_io(handle, &link->io);
|
||||
if (i == CS_SUCCESS) break;
|
||||
next_entry:
|
||||
CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
|
||||
}
|
||||
|
||||
CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
|
||||
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
|
||||
|
||||
/* A bad hack... */
|
||||
release_region(link->io.BasePort1, link->io.NumPorts1);
|
||||
|
||||
/* Set configuration options for the fdomain driver */
|
||||
sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ);
|
||||
fdomain_setup(str);
|
||||
|
||||
host = __fdomain_16x0_detect(&fdomain_driver_template);
|
||||
if (!host) {
|
||||
printk(KERN_INFO "fdomain_cs: no SCSI devices found\n");
|
||||
goto cs_failed;
|
||||
}
|
||||
|
||||
scsi_add_host(host, NULL); /* XXX handle failure */
|
||||
scsi_scan_host(host);
|
||||
|
||||
sprintf(info->node.dev_name, "scsi%d", host->host_no);
|
||||
link->dev = &info->node;
|
||||
info->host = host;
|
||||
|
||||
link->state &= ~DEV_CONFIG_PENDING;
|
||||
return;
|
||||
|
||||
cs_failed:
|
||||
cs_error(link->handle, last_fn, last_ret);
|
||||
fdomain_release(link);
|
||||
return;
|
||||
|
||||
} /* fdomain_config */
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static void fdomain_release(dev_link_t *link)
|
||||
{
|
||||
scsi_info_t *info = link->priv;
|
||||
|
||||
DEBUG(0, "fdomain_release(0x%p)\n", link);
|
||||
|
||||
scsi_remove_host(info->host);
|
||||
link->dev = NULL;
|
||||
|
||||
pcmcia_release_configuration(link->handle);
|
||||
pcmcia_release_io(link->handle, &link->io);
|
||||
pcmcia_release_irq(link->handle, &link->irq);
|
||||
|
||||
scsi_unregister(info->host);
|
||||
|
||||
link->state &= ~DEV_CONFIG;
|
||||
}
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static int fdomain_event(event_t event, int priority,
|
||||
event_callback_args_t *args)
|
||||
{
|
||||
dev_link_t *link = args->client_data;
|
||||
|
||||
DEBUG(1, "fdomain_event(0x%06x)\n", event);
|
||||
|
||||
switch (event) {
|
||||
case CS_EVENT_CARD_REMOVAL:
|
||||
link->state &= ~DEV_PRESENT;
|
||||
if (link->state & DEV_CONFIG)
|
||||
fdomain_release(link);
|
||||
break;
|
||||
case CS_EVENT_CARD_INSERTION:
|
||||
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
|
||||
fdomain_config(link);
|
||||
break;
|
||||
case CS_EVENT_PM_SUSPEND:
|
||||
link->state |= DEV_SUSPEND;
|
||||
/* Fall through... */
|
||||
case CS_EVENT_RESET_PHYSICAL:
|
||||
if (link->state & DEV_CONFIG)
|
||||
pcmcia_release_configuration(link->handle);
|
||||
break;
|
||||
case CS_EVENT_PM_RESUME:
|
||||
link->state &= ~DEV_SUSPEND;
|
||||
/* Fall through... */
|
||||
case CS_EVENT_CARD_RESET:
|
||||
if (link->state & DEV_CONFIG) {
|
||||
pcmcia_request_configuration(link->handle, &link->conf);
|
||||
fdomain_16x0_bus_reset(NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
} /* fdomain_event */
|
||||
|
||||
static struct pcmcia_driver fdomain_cs_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.drv = {
|
||||
.name = "fdomain_cs",
|
||||
},
|
||||
.attach = fdomain_attach,
|
||||
.detach = fdomain_detach,
|
||||
};
|
||||
|
||||
static int __init init_fdomain_cs(void)
|
||||
{
|
||||
return pcmcia_register_driver(&fdomain_cs_driver);
|
||||
}
|
||||
|
||||
static void __exit exit_fdomain_cs(void)
|
||||
{
|
||||
pcmcia_unregister_driver(&fdomain_cs_driver);
|
||||
BUG_ON(dev_list != NULL);
|
||||
}
|
||||
|
||||
module_init(init_fdomain_cs);
|
||||
module_exit(exit_fdomain_cs);
|
||||
2198
drivers/scsi/pcmcia/nsp_cs.c
Normal file
2198
drivers/scsi/pcmcia/nsp_cs.c
Normal file
File diff suppressed because it is too large
Load Diff
472
drivers/scsi/pcmcia/nsp_cs.h
Normal file
472
drivers/scsi/pcmcia/nsp_cs.h
Normal file
@@ -0,0 +1,472 @@
|
||||
/*=======================================================/
|
||||
Header file for nsp_cs.c
|
||||
By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
|
||||
|
||||
Ver.1.0 : Cut unused lines.
|
||||
Ver 0.1 : Initial version.
|
||||
|
||||
This software may be used and distributed according to the terms of
|
||||
the GNU General Public License.
|
||||
|
||||
=========================================================*/
|
||||
|
||||
/* $Id: nsp_cs.h,v 1.19 2003/08/18 11:09:19 elca Exp $ */
|
||||
|
||||
#ifndef __nsp_cs__
|
||||
#define __nsp_cs__
|
||||
|
||||
/* for debugging */
|
||||
//#define NSP_DEBUG 9
|
||||
|
||||
/*
|
||||
#define static
|
||||
#define inline
|
||||
*/
|
||||
|
||||
/************************************
|
||||
* Some useful macros...
|
||||
*/
|
||||
#define BIT(x) (1L << (x))
|
||||
|
||||
/* SCSI initiator must be ID 7 */
|
||||
#define NSP_INITIATOR_ID 7
|
||||
|
||||
#define NSP_SELTIMEOUT 200
|
||||
|
||||
/***************************************************************************
|
||||
* register definitions
|
||||
***************************************************************************/
|
||||
/*========================================================================
|
||||
* base register
|
||||
========================================================================*/
|
||||
#define IRQCONTROL 0x00 /* R */
|
||||
# define IRQCONTROL_RESELECT_CLEAR BIT(0)
|
||||
# define IRQCONTROL_PHASE_CHANGE_CLEAR BIT(1)
|
||||
# define IRQCONTROL_TIMER_CLEAR BIT(2)
|
||||
# define IRQCONTROL_FIFO_CLEAR BIT(3)
|
||||
# define IRQCONTROL_ALLMASK 0xff
|
||||
# define IRQCONTROL_ALLCLEAR (IRQCONTROL_RESELECT_CLEAR | \
|
||||
IRQCONTROL_PHASE_CHANGE_CLEAR | \
|
||||
IRQCONTROL_TIMER_CLEAR | \
|
||||
IRQCONTROL_FIFO_CLEAR )
|
||||
# define IRQCONTROL_IRQDISABLE 0xf0
|
||||
|
||||
#define IRQSTATUS 0x00 /* W */
|
||||
# define IRQSTATUS_SCSI BIT(0)
|
||||
# define IRQSTATUS_TIMER BIT(2)
|
||||
# define IRQSTATUS_FIFO BIT(3)
|
||||
# define IRQSTATUS_MASK 0x0f
|
||||
|
||||
#define IFSELECT 0x01 /* W */
|
||||
# define IF_IFSEL BIT(0)
|
||||
# define IF_REGSEL BIT(2)
|
||||
|
||||
#define FIFOSTATUS 0x01 /* R */
|
||||
# define FIFOSTATUS_CHIP_REVISION_MASK 0x0f
|
||||
# define FIFOSTATUS_CHIP_ID_MASK 0x70
|
||||
# define FIFOSTATUS_FULL_EMPTY BIT(7)
|
||||
|
||||
#define INDEXREG 0x02 /* R/W */
|
||||
#define DATAREG 0x03 /* R/W */
|
||||
#define FIFODATA 0x04 /* R/W */
|
||||
#define FIFODATA1 0x05 /* R/W */
|
||||
#define FIFODATA2 0x06 /* R/W */
|
||||
#define FIFODATA3 0x07 /* R/W */
|
||||
|
||||
/*====================================================================
|
||||
* indexed register
|
||||
====================================================================*/
|
||||
#define EXTBUSCTRL 0x10 /* R/W,deleted */
|
||||
|
||||
#define CLOCKDIV 0x11 /* R/W */
|
||||
# define CLOCK_40M 0x02
|
||||
# define CLOCK_20M 0x01
|
||||
# define FAST_20 BIT(2)
|
||||
|
||||
#define TERMPWRCTRL 0x13 /* R/W */
|
||||
# define POWER_ON BIT(0)
|
||||
|
||||
#define SCSIIRQMODE 0x15 /* R/W */
|
||||
# define SCSI_PHASE_CHANGE_EI BIT(0)
|
||||
# define RESELECT_EI BIT(4)
|
||||
# define FIFO_IRQ_EI BIT(5)
|
||||
# define SCSI_RESET_IRQ_EI BIT(6)
|
||||
|
||||
#define IRQPHASESENCE 0x16 /* R */
|
||||
# define LATCHED_MSG BIT(0)
|
||||
# define LATCHED_IO BIT(1)
|
||||
# define LATCHED_CD BIT(2)
|
||||
# define LATCHED_BUS_FREE BIT(3)
|
||||
# define PHASE_CHANGE_IRQ BIT(4)
|
||||
# define RESELECT_IRQ BIT(5)
|
||||
# define FIFO_IRQ BIT(6)
|
||||
# define SCSI_RESET_IRQ BIT(7)
|
||||
|
||||
#define TIMERCOUNT 0x17 /* R/W */
|
||||
|
||||
#define SCSIBUSCTRL 0x18 /* R/W */
|
||||
# define SCSI_SEL BIT(0)
|
||||
# define SCSI_RST BIT(1)
|
||||
# define SCSI_DATAOUT_ENB BIT(2)
|
||||
# define SCSI_ATN BIT(3)
|
||||
# define SCSI_ACK BIT(4)
|
||||
# define SCSI_BSY BIT(5)
|
||||
# define AUTODIRECTION BIT(6)
|
||||
# define ACKENB BIT(7)
|
||||
|
||||
#define SCSIBUSMON 0x19 /* R */
|
||||
|
||||
#define SETARBIT 0x1A /* W */
|
||||
# define ARBIT_GO BIT(0)
|
||||
# define ARBIT_FLAG_CLEAR BIT(1)
|
||||
|
||||
#define ARBITSTATUS 0x1A /* R */
|
||||
/*# define ARBIT_GO BIT(0)*/
|
||||
# define ARBIT_WIN BIT(1)
|
||||
# define ARBIT_FAIL BIT(2)
|
||||
# define RESELECT_FLAG BIT(3)
|
||||
|
||||
#define PARITYCTRL 0x1B /* W */
|
||||
#define PARITYSTATUS 0x1B /* R */
|
||||
|
||||
#define COMMANDCTRL 0x1C /* W */
|
||||
# define CLEAR_COMMAND_POINTER BIT(0)
|
||||
# define AUTO_COMMAND_GO BIT(1)
|
||||
|
||||
#define RESELECTID 0x1C /* R */
|
||||
#define COMMANDDATA 0x1D /* R/W */
|
||||
|
||||
#define POINTERCLR 0x1E /* W */
|
||||
# define POINTER_CLEAR BIT(0)
|
||||
# define ACK_COUNTER_CLEAR BIT(1)
|
||||
# define REQ_COUNTER_CLEAR BIT(2)
|
||||
# define HOST_COUNTER_CLEAR BIT(3)
|
||||
# define READ_SOURCE (BIT(4) | BIT(5))
|
||||
# define ACK_COUNTER (0)
|
||||
# define REQ_COUNTER (BIT(4))
|
||||
# define HOST_COUNTER (BIT(5))
|
||||
|
||||
#define TRANSFERCOUNT 0x1E /* R */
|
||||
|
||||
#define TRANSFERMODE 0x20 /* R/W */
|
||||
# define MODE_MEM8 BIT(0)
|
||||
# define MODE_MEM32 BIT(1)
|
||||
# define MODE_ADR24 BIT(2)
|
||||
# define MODE_ADR32 BIT(3)
|
||||
# define MODE_IO8 BIT(4)
|
||||
# define MODE_IO32 BIT(5)
|
||||
# define TRANSFER_GO BIT(6)
|
||||
# define BRAIND BIT(7)
|
||||
|
||||
#define SYNCREG 0x21 /* R/W */
|
||||
# define SYNCREG_OFFSET_MASK 0x0f
|
||||
# define SYNCREG_PERIOD_MASK 0xf0
|
||||
# define SYNCREG_PERIOD_SHIFT 4
|
||||
|
||||
#define SCSIDATALATCH 0x22 /* W */
|
||||
#define SCSIDATAIN 0x22 /* R */
|
||||
#define SCSIDATAWITHACK 0x23 /* R/W */
|
||||
#define SCAMCONTROL 0x24 /* W */
|
||||
#define SCAMSTATUS 0x24 /* R */
|
||||
#define SCAMDATA 0x25 /* R/W */
|
||||
|
||||
#define OTHERCONTROL 0x26 /* R/W */
|
||||
# define TPL_ROM_WRITE_EN BIT(0)
|
||||
# define TPWR_OUT BIT(1)
|
||||
# define TPWR_SENSE BIT(2)
|
||||
# define RA8_CONTROL BIT(3)
|
||||
|
||||
#define ACKWIDTH 0x27 /* R/W */
|
||||
#define CLRTESTPNT 0x28 /* W */
|
||||
#define ACKCNTLD 0x29 /* W */
|
||||
#define REQCNTLD 0x2A /* W */
|
||||
#define HSTCNTLD 0x2B /* W */
|
||||
#define CHECKSUM 0x2C /* R/W */
|
||||
|
||||
/************************************************************************
|
||||
* Input status bit definitions.
|
||||
************************************************************************/
|
||||
#define S_MESSAGE BIT(0) /* Message line from SCSI bus */
|
||||
#define S_IO BIT(1) /* Input/Output line from SCSI bus */
|
||||
#define S_CD BIT(2) /* Command/Data line from SCSI bus */
|
||||
#define S_BUSY BIT(3) /* Busy line from SCSI bus */
|
||||
#define S_ACK BIT(4) /* Acknowlege line from SCSI bus */
|
||||
#define S_REQUEST BIT(5) /* Request line from SCSI bus */
|
||||
#define S_SELECT BIT(6) /* */
|
||||
#define S_ATN BIT(7) /* */
|
||||
|
||||
/***********************************************************************
|
||||
* Useful Bus Monitor status combinations.
|
||||
***********************************************************************/
|
||||
#define BUSMON_SEL S_SELECT
|
||||
#define BUSMON_BSY S_BUSY
|
||||
#define BUSMON_REQ S_REQUEST
|
||||
#define BUSMON_IO S_IO
|
||||
#define BUSMON_ACK S_ACK
|
||||
#define BUSMON_BUS_FREE 0
|
||||
#define BUSMON_COMMAND ( S_BUSY | S_CD | S_REQUEST )
|
||||
#define BUSMON_MESSAGE_IN ( S_BUSY | S_CD | S_IO | S_MESSAGE | S_REQUEST )
|
||||
#define BUSMON_MESSAGE_OUT ( S_BUSY | S_CD | S_MESSAGE | S_REQUEST )
|
||||
#define BUSMON_DATA_IN ( S_BUSY | S_IO | S_REQUEST )
|
||||
#define BUSMON_DATA_OUT ( S_BUSY | S_REQUEST )
|
||||
#define BUSMON_STATUS ( S_BUSY | S_CD | S_IO | S_REQUEST )
|
||||
#define BUSMON_SELECT ( S_IO | S_SELECT )
|
||||
#define BUSMON_RESELECT ( S_IO | S_SELECT )
|
||||
#define BUSMON_PHASE_MASK ( S_CD | S_IO | S_MESSAGE | S_SELECT )
|
||||
|
||||
#define BUSPHASE_SELECT ( BUSMON_SELECT & BUSMON_PHASE_MASK )
|
||||
#define BUSPHASE_COMMAND ( BUSMON_COMMAND & BUSMON_PHASE_MASK )
|
||||
#define BUSPHASE_MESSAGE_IN ( BUSMON_MESSAGE_IN & BUSMON_PHASE_MASK )
|
||||
#define BUSPHASE_MESSAGE_OUT ( BUSMON_MESSAGE_OUT & BUSMON_PHASE_MASK )
|
||||
#define BUSPHASE_DATA_IN ( BUSMON_DATA_IN & BUSMON_PHASE_MASK )
|
||||
#define BUSPHASE_DATA_OUT ( BUSMON_DATA_OUT & BUSMON_PHASE_MASK )
|
||||
#define BUSPHASE_STATUS ( BUSMON_STATUS & BUSMON_PHASE_MASK )
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
typedef struct scsi_info_t {
|
||||
dev_link_t link;
|
||||
struct Scsi_Host *host;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
|
||||
dev_node_t node;
|
||||
#else
|
||||
int ndev;
|
||||
dev_node_t node[8];
|
||||
struct bus_operations *bus;
|
||||
#endif
|
||||
int stop;
|
||||
} scsi_info_t;
|
||||
|
||||
|
||||
/* synchronous transfer negotiation data */
|
||||
typedef struct _sync_data {
|
||||
unsigned int SyncNegotiation;
|
||||
#define SYNC_NOT_YET 0
|
||||
#define SYNC_OK 1
|
||||
#define SYNC_NG 2
|
||||
|
||||
unsigned int SyncPeriod;
|
||||
unsigned int SyncOffset;
|
||||
unsigned char SyncRegister;
|
||||
unsigned char AckWidth;
|
||||
} sync_data;
|
||||
|
||||
typedef struct _nsp_hw_data {
|
||||
unsigned int BaseAddress;
|
||||
unsigned int NumAddress;
|
||||
unsigned int IrqNumber;
|
||||
|
||||
unsigned long MmioAddress;
|
||||
#define NSP_MMIO_OFFSET 0x0800
|
||||
unsigned long MmioLength;
|
||||
|
||||
unsigned char ScsiClockDiv;
|
||||
|
||||
unsigned char TransferMode;
|
||||
|
||||
int TimerCount;
|
||||
int SelectionTimeOut;
|
||||
Scsi_Cmnd *CurrentSC;
|
||||
//int CurrnetTarget;
|
||||
|
||||
int FifoCount;
|
||||
|
||||
#define MSGBUF_SIZE 20
|
||||
unsigned char MsgBuffer[MSGBUF_SIZE];
|
||||
int MsgLen;
|
||||
|
||||
#define N_TARGET 8
|
||||
sync_data Sync[N_TARGET];
|
||||
|
||||
char nspinfo[110]; /* description */
|
||||
spinlock_t Lock;
|
||||
|
||||
scsi_info_t *ScsiInfo; /* attach <-> detect glue */
|
||||
|
||||
|
||||
#ifdef NSP_DEBUG
|
||||
int CmdId; /* Accepted command serial number.
|
||||
Used for debugging. */
|
||||
#endif
|
||||
} nsp_hw_data;
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
*/
|
||||
|
||||
/* Card service functions */
|
||||
static dev_link_t *nsp_cs_attach (void);
|
||||
static void nsp_cs_detach (dev_link_t *link);
|
||||
static void nsp_cs_release(dev_link_t *link);
|
||||
static void nsp_cs_config (dev_link_t *link);
|
||||
static int nsp_cs_event (event_t event, int priority, event_callback_args_t *args);
|
||||
|
||||
/* Linux SCSI subsystem specific functions */
|
||||
static struct Scsi_Host *nsp_detect (Scsi_Host_Template *sht);
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
|
||||
static int nsp_detect_old (Scsi_Host_Template *sht);
|
||||
static int nsp_release_old(struct Scsi_Host *shpnt);
|
||||
#endif
|
||||
static const char *nsp_info (struct Scsi_Host *shpnt);
|
||||
static int nsp_proc_info (
|
||||
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
|
||||
struct Scsi_Host *host,
|
||||
#endif
|
||||
char *buffer,
|
||||
char **start,
|
||||
off_t offset,
|
||||
int length,
|
||||
#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
|
||||
int hostno,
|
||||
#endif
|
||||
int inout);
|
||||
static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (* done)(Scsi_Cmnd *SCpnt));
|
||||
|
||||
/* Error handler */
|
||||
/*static int nsp_eh_abort (Scsi_Cmnd *SCpnt);*/
|
||||
/*static int nsp_eh_device_reset(Scsi_Cmnd *SCpnt);*/
|
||||
static int nsp_eh_bus_reset (Scsi_Cmnd *SCpnt);
|
||||
static int nsp_eh_host_reset (Scsi_Cmnd *SCpnt);
|
||||
static int nsp_bus_reset (nsp_hw_data *data);
|
||||
|
||||
/* */
|
||||
static int nsphw_init (nsp_hw_data *data);
|
||||
static int nsphw_start_selection(Scsi_Cmnd *SCpnt);
|
||||
static void nsp_start_timer (Scsi_Cmnd *SCpnt, int time);
|
||||
static int nsp_fifo_count (Scsi_Cmnd *SCpnt);
|
||||
static void nsp_pio_read (Scsi_Cmnd *SCpnt);
|
||||
static void nsp_pio_write (Scsi_Cmnd *SCpnt);
|
||||
static int nsp_nexus (Scsi_Cmnd *SCpnt);
|
||||
static void nsp_scsi_done (Scsi_Cmnd *SCpnt);
|
||||
static int nsp_analyze_sdtr (Scsi_Cmnd *SCpnt);
|
||||
static int nsp_negate_signal (Scsi_Cmnd *SCpnt, unsigned char mask, char *str);
|
||||
static int nsp_expect_signal (Scsi_Cmnd *SCpnt, unsigned char current_phase, unsigned char mask);
|
||||
static int nsp_xfer (Scsi_Cmnd *SCpnt, int phase);
|
||||
static int nsp_dataphase_bypass (Scsi_Cmnd *SCpnt);
|
||||
static int nsp_reselected (Scsi_Cmnd *SCpnt);
|
||||
static struct Scsi_Host *nsp_detect(Scsi_Host_Template *sht);
|
||||
|
||||
/* Interrupt handler */
|
||||
//static irqreturn_t nspintr(int irq, void *dev_id, struct pt_regs *regs);
|
||||
|
||||
/* Module entry point*/
|
||||
static int __init nsp_cs_init(void);
|
||||
static void __exit nsp_cs_exit(void);
|
||||
|
||||
|
||||
/* Debug */
|
||||
#ifdef NSP_DEBUG
|
||||
static void show_command (Scsi_Cmnd *SCpnt);
|
||||
static void show_phase (Scsi_Cmnd *SCpnt);
|
||||
static void show_busphase(unsigned char stat);
|
||||
static void show_message (nsp_hw_data *data);
|
||||
#else
|
||||
# define show_command(ptr) /* */
|
||||
# define show_phase(SCpnt) /* */
|
||||
# define show_busphase(stat) /* */
|
||||
# define show_message(data) /* */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SCSI phase
|
||||
*/
|
||||
enum _scsi_phase {
|
||||
PH_UNDETERMINED ,
|
||||
PH_ARBSTART ,
|
||||
PH_SELSTART ,
|
||||
PH_SELECTED ,
|
||||
PH_COMMAND ,
|
||||
PH_DATA ,
|
||||
PH_STATUS ,
|
||||
PH_MSG_IN ,
|
||||
PH_MSG_OUT ,
|
||||
PH_DISCONNECT ,
|
||||
PH_RESELECT ,
|
||||
PH_ABORT ,
|
||||
PH_RESET
|
||||
};
|
||||
|
||||
enum _data_in_out {
|
||||
IO_UNKNOWN,
|
||||
IO_IN,
|
||||
IO_OUT
|
||||
};
|
||||
|
||||
enum _burst_mode {
|
||||
BURST_IO8 = 0,
|
||||
BURST_IO32 = 1,
|
||||
BURST_MEM32 = 2,
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* SCSI messaage
|
||||
*/
|
||||
#define MSG_COMMAND_COMPLETE 0x00
|
||||
#define MSG_EXTENDED 0x01
|
||||
#define MSG_ABORT 0x06
|
||||
#define MSG_NO_OPERATION 0x08
|
||||
#define MSG_BUS_DEVICE_RESET 0x0c
|
||||
|
||||
#define MSG_EXT_SDTR 0x01
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* Compatibility functions
|
||||
*/
|
||||
|
||||
/* for Kernel 2.4 */
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
|
||||
# define scsi_register_host(template) scsi_register_module(MODULE_SCSI_HA, template)
|
||||
# define scsi_unregister_host(template) scsi_unregister_module(MODULE_SCSI_HA, template)
|
||||
# define scsi_host_put(host) scsi_unregister(host)
|
||||
|
||||
typedef void irqreturn_t;
|
||||
# define IRQ_NONE /* */
|
||||
# define IRQ_HANDLED /* */
|
||||
# define IRQ_RETVAL(x) /* */
|
||||
|
||||
/* This is ad-hoc version of scsi_host_get_next() */
|
||||
static inline struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *host)
|
||||
{
|
||||
if (host == NULL) {
|
||||
return scsi_hostlist;
|
||||
} else {
|
||||
return host->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is ad-hoc version of scsi_host_hn_get() */
|
||||
static inline struct Scsi_Host *scsi_host_hn_get(unsigned short hostno)
|
||||
{
|
||||
struct Scsi_Host *host;
|
||||
|
||||
for (host = scsi_host_get_next(NULL); host != NULL;
|
||||
host = scsi_host_get_next(host)) {
|
||||
if (host->host_no == hostno) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
static void cs_error(client_handle_t handle, int func, int ret)
|
||||
{
|
||||
error_info_t err = { func, ret };
|
||||
pcmcia_report_error(handle, &err);
|
||||
}
|
||||
|
||||
/* scatter-gather table */
|
||||
# define BUFFER_ADDR (SCpnt->SCp.buffer->address)
|
||||
#endif
|
||||
|
||||
/* for Kernel 2.6 */
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
|
||||
/* scatter-gather table */
|
||||
# define BUFFER_ADDR ((char *)((unsigned int)(SCpnt->SCp.buffer->page) + SCpnt->SCp.buffer->offset))
|
||||
#endif
|
||||
|
||||
#endif /*__nsp_cs__*/
|
||||
/* end */
|
||||
215
drivers/scsi/pcmcia/nsp_debug.c
Normal file
215
drivers/scsi/pcmcia/nsp_debug.c
Normal file
@@ -0,0 +1,215 @@
|
||||
/*========================================================================
|
||||
Debug routines for nsp_cs
|
||||
By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
|
||||
|
||||
This software may be used and distributed according to the terms of
|
||||
the GNU General Public License.
|
||||
=========================================================================*/
|
||||
|
||||
/* $Id: nsp_debug.c,v 1.3 2003/07/26 14:21:09 elca Exp $ */
|
||||
|
||||
/*
|
||||
* Show the command data of a command
|
||||
*/
|
||||
static const char unknown[] = "UNKNOWN";
|
||||
|
||||
static const char * group_0_commands[] = {
|
||||
/* 00-03 */ "Test Unit Ready", "Rezero Unit", unknown, "Request Sense",
|
||||
/* 04-07 */ "Format Unit", "Read Block Limits", unknown, "Reasssign Blocks",
|
||||
/* 08-0d */ "Read (6)", unknown, "Write (6)", "Seek (6)", unknown, unknown,
|
||||
/* 0e-12 */ unknown, "Read Reverse", "Write Filemarks", "Space", "Inquiry",
|
||||
/* 13-16 */ unknown, "Recover Buffered Data", "Mode Select", "Reserve",
|
||||
/* 17-1b */ "Release", "Copy", "Erase", "Mode Sense", "Start/Stop Unit",
|
||||
/* 1c-1d */ "Receive Diagnostic", "Send Diagnostic",
|
||||
/* 1e-1f */ "Prevent/Allow Medium Removal", unknown,
|
||||
};
|
||||
|
||||
|
||||
static const char *group_1_commands[] = {
|
||||
/* 20-22 */ unknown, unknown, unknown,
|
||||
/* 23-28 */ unknown, unknown, "Read Capacity", unknown, unknown, "Read (10)",
|
||||
/* 29-2d */ unknown, "Write (10)", "Seek (10)", unknown, unknown,
|
||||
/* 2e-31 */ "Write Verify","Verify", "Search High", "Search Equal",
|
||||
/* 32-34 */ "Search Low", "Set Limits", "Prefetch or Read Position",
|
||||
/* 35-37 */ "Synchronize Cache","Lock/Unlock Cache", "Read Defect Data",
|
||||
/* 38-3c */ "Medium Scan", "Compare","Copy Verify", "Write Buffer", "Read Buffer",
|
||||
/* 3d-3f */ "Update Block", "Read Long", "Write Long",
|
||||
};
|
||||
|
||||
|
||||
static const char *group_2_commands[] = {
|
||||
/* 40-41 */ "Change Definition", "Write Same",
|
||||
/* 42-48 */ "Read Sub-Ch(cd)", "Read TOC", "Read Header(cd)", "Play Audio(cd)", unknown, "Play Audio MSF(cd)", "Play Audio Track/Index(cd)",
|
||||
/* 49-4f */ "Play Track Relative(10)(cd)", unknown, "Pause/Resume(cd)", "Log Select", "Log Sense", unknown, unknown,
|
||||
/* 50-55 */ unknown, unknown, unknown, unknown, unknown, "Mode Select (10)",
|
||||
/* 56-5b */ unknown, unknown, unknown, unknown, "Mode Sense (10)", unknown,
|
||||
/* 5c-5f */ unknown, unknown, unknown,
|
||||
};
|
||||
|
||||
#define group(opcode) (((opcode) >> 5) & 7)
|
||||
|
||||
#define RESERVED_GROUP 0
|
||||
#define VENDOR_GROUP 1
|
||||
#define NOTEXT_GROUP 2
|
||||
|
||||
static const char **commands[] = {
|
||||
group_0_commands, group_1_commands, group_2_commands,
|
||||
(const char **) RESERVED_GROUP, (const char **) RESERVED_GROUP,
|
||||
(const char **) NOTEXT_GROUP, (const char **) VENDOR_GROUP,
|
||||
(const char **) VENDOR_GROUP
|
||||
};
|
||||
|
||||
static const char reserved[] = "RESERVED";
|
||||
static const char vendor[] = "VENDOR SPECIFIC";
|
||||
|
||||
static void print_opcodek(unsigned char opcode)
|
||||
{
|
||||
const char **table = commands[ group(opcode) ];
|
||||
|
||||
switch ((unsigned long) table) {
|
||||
case RESERVED_GROUP:
|
||||
printk("%s[%02x] ", reserved, opcode);
|
||||
break;
|
||||
case NOTEXT_GROUP:
|
||||
printk("%s(notext)[%02x] ", unknown, opcode);
|
||||
break;
|
||||
case VENDOR_GROUP:
|
||||
printk("%s[%02x] ", vendor, opcode);
|
||||
break;
|
||||
default:
|
||||
if (table[opcode & 0x1f] != unknown)
|
||||
printk("%s[%02x] ", table[opcode & 0x1f], opcode);
|
||||
else
|
||||
printk("%s[%02x] ", unknown, opcode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void print_commandk (unsigned char *command)
|
||||
{
|
||||
int i, s;
|
||||
printk(KERN_DEBUG);
|
||||
print_opcodek(command[0]);
|
||||
/*printk(KERN_DEBUG "%s ", __FUNCTION__);*/
|
||||
if ((command[0] >> 5) == 6 ||
|
||||
(command[0] >> 5) == 7 ) {
|
||||
s = 12; /* vender specific */
|
||||
} else {
|
||||
s = COMMAND_SIZE(command[0]);
|
||||
}
|
||||
for ( i = 1; i < s; ++i) {
|
||||
printk("%02x ", command[i]);
|
||||
}
|
||||
|
||||
switch (s) {
|
||||
case 6:
|
||||
printk("LBA=%d len=%d",
|
||||
(((unsigned int)command[1] & 0x0f) << 16) |
|
||||
( (unsigned int)command[2] << 8) |
|
||||
( (unsigned int)command[3] ),
|
||||
(unsigned int)command[4]
|
||||
);
|
||||
break;
|
||||
case 10:
|
||||
printk("LBA=%d len=%d",
|
||||
((unsigned int)command[2] << 24) |
|
||||
((unsigned int)command[3] << 16) |
|
||||
((unsigned int)command[4] << 8) |
|
||||
((unsigned int)command[5] ),
|
||||
((unsigned int)command[7] << 8) |
|
||||
((unsigned int)command[8] )
|
||||
);
|
||||
break;
|
||||
case 12:
|
||||
printk("LBA=%d len=%d",
|
||||
((unsigned int)command[2] << 24) |
|
||||
((unsigned int)command[3] << 16) |
|
||||
((unsigned int)command[4] << 8) |
|
||||
((unsigned int)command[5] ),
|
||||
((unsigned int)command[6] << 24) |
|
||||
((unsigned int)command[7] << 16) |
|
||||
((unsigned int)command[8] << 8) |
|
||||
((unsigned int)command[9] )
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
static void show_command(Scsi_Cmnd *SCpnt)
|
||||
{
|
||||
print_commandk(SCpnt->cmnd);
|
||||
}
|
||||
|
||||
static void show_phase(Scsi_Cmnd *SCpnt)
|
||||
{
|
||||
int i = SCpnt->SCp.phase;
|
||||
|
||||
char *ph[] = {
|
||||
"PH_UNDETERMINED",
|
||||
"PH_ARBSTART",
|
||||
"PH_SELSTART",
|
||||
"PH_SELECTED",
|
||||
"PH_COMMAND",
|
||||
"PH_DATA",
|
||||
"PH_STATUS",
|
||||
"PH_MSG_IN",
|
||||
"PH_MSG_OUT",
|
||||
"PH_DISCONNECT",
|
||||
"PH_RESELECT"
|
||||
};
|
||||
|
||||
if ( i < PH_UNDETERMINED || i > PH_RESELECT ) {
|
||||
printk(KERN_DEBUG "scsi phase: unknown(%d)\n", i);
|
||||
return;
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "scsi phase: %s\n", ph[i]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void show_busphase(unsigned char stat)
|
||||
{
|
||||
switch(stat) {
|
||||
case BUSPHASE_COMMAND:
|
||||
printk(KERN_DEBUG "BUSPHASE_COMMAND\n");
|
||||
break;
|
||||
case BUSPHASE_MESSAGE_IN:
|
||||
printk(KERN_DEBUG "BUSPHASE_MESSAGE_IN\n");
|
||||
break;
|
||||
case BUSPHASE_MESSAGE_OUT:
|
||||
printk(KERN_DEBUG "BUSPHASE_MESSAGE_OUT\n");
|
||||
break;
|
||||
case BUSPHASE_DATA_IN:
|
||||
printk(KERN_DEBUG "BUSPHASE_DATA_IN\n");
|
||||
break;
|
||||
case BUSPHASE_DATA_OUT:
|
||||
printk(KERN_DEBUG "BUSPHASE_DATA_OUT\n");
|
||||
break;
|
||||
case BUSPHASE_STATUS:
|
||||
printk(KERN_DEBUG "BUSPHASE_STATUS\n");
|
||||
break;
|
||||
case BUSPHASE_SELECT:
|
||||
printk(KERN_DEBUG "BUSPHASE_SELECT\n");
|
||||
break;
|
||||
default:
|
||||
printk(KERN_DEBUG "BUSPHASE_other\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void show_message(nsp_hw_data *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
printk(KERN_DEBUG "msg:");
|
||||
for(i=0; i < data->MsgLen; i++) {
|
||||
printk(" %02x", data->MsgBuffer[i]);
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
/* end */
|
||||
274
drivers/scsi/pcmcia/nsp_io.h
Normal file
274
drivers/scsi/pcmcia/nsp_io.h
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
NinjaSCSI I/O funtions
|
||||
By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
|
||||
|
||||
This software may be used and distributed according to the terms of
|
||||
the GNU General Public License.
|
||||
|
||||
*/
|
||||
|
||||
/* $Id: nsp_io.h,v 1.3 2003/08/04 21:15:26 elca Exp $ */
|
||||
|
||||
#ifndef __NSP_IO_H__
|
||||
#define __NSP_IO_H__
|
||||
|
||||
static inline void nsp_write(unsigned int base,
|
||||
unsigned int index,
|
||||
unsigned char val);
|
||||
static inline unsigned char nsp_read(unsigned int base,
|
||||
unsigned int index);
|
||||
static inline void nsp_index_write(unsigned int BaseAddr,
|
||||
unsigned int Register,
|
||||
unsigned char Value);
|
||||
static inline unsigned char nsp_index_read(unsigned int BaseAddr,
|
||||
unsigned int Register);
|
||||
|
||||
/*******************************************************************
|
||||
* Basic IO
|
||||
*/
|
||||
|
||||
static inline void nsp_write(unsigned int base,
|
||||
unsigned int index,
|
||||
unsigned char val)
|
||||
{
|
||||
outb(val, (base + index));
|
||||
}
|
||||
|
||||
static inline unsigned char nsp_read(unsigned int base,
|
||||
unsigned int index)
|
||||
{
|
||||
return inb(base + index);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Indexed IO
|
||||
*/
|
||||
static inline unsigned char nsp_index_read(unsigned int BaseAddr,
|
||||
unsigned int Register)
|
||||
{
|
||||
outb(Register, BaseAddr + INDEXREG);
|
||||
return inb(BaseAddr + DATAREG);
|
||||
}
|
||||
|
||||
static inline void nsp_index_write(unsigned int BaseAddr,
|
||||
unsigned int Register,
|
||||
unsigned char Value)
|
||||
{
|
||||
outb(Register, BaseAddr + INDEXREG);
|
||||
outb(Value, BaseAddr + DATAREG);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* fifo func
|
||||
*/
|
||||
|
||||
/* read 8 bit FIFO */
|
||||
static inline void nsp_multi_read_1(unsigned int BaseAddr,
|
||||
unsigned int Register,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
insb(BaseAddr + Register, buf, count);
|
||||
}
|
||||
|
||||
static inline void nsp_fifo8_read(unsigned int base,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
/*nsp_dbg(NSP_DEBUG_DATA_IO, "buf=0x%p, count=0x%lx", buf, count);*/
|
||||
nsp_multi_read_1(base, FIFODATA, buf, count);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
/* read 16 bit FIFO */
|
||||
static inline void nsp_multi_read_2(unsigned int BaseAddr,
|
||||
unsigned int Register,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
insw(BaseAddr + Register, buf, count);
|
||||
}
|
||||
|
||||
static inline void nsp_fifo16_read(unsigned int base,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
//nsp_dbg(NSP_DEBUG_DATA_IO, "buf=0x%p, count=0x%lx*2", buf, count);
|
||||
nsp_multi_read_2(base, FIFODATA, buf, count);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
|
||||
/* read 32bit FIFO */
|
||||
static inline void nsp_multi_read_4(unsigned int BaseAddr,
|
||||
unsigned int Register,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
insl(BaseAddr + Register, buf, count);
|
||||
}
|
||||
|
||||
static inline void nsp_fifo32_read(unsigned int base,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
//nsp_dbg(NSP_DEBUG_DATA_IO, "buf=0x%p, count=0x%lx*4", buf, count);
|
||||
nsp_multi_read_4(base, FIFODATA, buf, count);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------*/
|
||||
|
||||
/* write 8bit FIFO */
|
||||
static inline void nsp_multi_write_1(unsigned int BaseAddr,
|
||||
unsigned int Register,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
outsb(BaseAddr + Register, buf, count);
|
||||
}
|
||||
|
||||
static inline void nsp_fifo8_write(unsigned int base,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
nsp_multi_write_1(base, FIFODATA, buf, count);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*/
|
||||
|
||||
/* write 16bit FIFO */
|
||||
static inline void nsp_multi_write_2(unsigned int BaseAddr,
|
||||
unsigned int Register,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
outsw(BaseAddr + Register, buf, count);
|
||||
}
|
||||
|
||||
static inline void nsp_fifo16_write(unsigned int base,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
nsp_multi_write_2(base, FIFODATA, buf, count);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*/
|
||||
|
||||
/* write 32bit FIFO */
|
||||
static inline void nsp_multi_write_4(unsigned int BaseAddr,
|
||||
unsigned int Register,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
outsl(BaseAddr + Register, buf, count);
|
||||
}
|
||||
|
||||
static inline void nsp_fifo32_write(unsigned int base,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
nsp_multi_write_4(base, FIFODATA, buf, count);
|
||||
}
|
||||
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static inline void nsp_mmio_write(unsigned long base,
|
||||
unsigned int index,
|
||||
unsigned char val)
|
||||
{
|
||||
unsigned char *ptr = (unsigned char *)(base + NSP_MMIO_OFFSET + index);
|
||||
|
||||
writeb(val, ptr);
|
||||
}
|
||||
|
||||
static inline unsigned char nsp_mmio_read(unsigned long base,
|
||||
unsigned int index)
|
||||
{
|
||||
unsigned char *ptr = (unsigned char *)(base + NSP_MMIO_OFFSET + index);
|
||||
|
||||
return readb(ptr);
|
||||
}
|
||||
|
||||
/*-----------*/
|
||||
|
||||
static inline unsigned char nsp_mmio_index_read(unsigned long base,
|
||||
unsigned int reg)
|
||||
{
|
||||
unsigned char *index_ptr = (unsigned char *)(base + NSP_MMIO_OFFSET + INDEXREG);
|
||||
unsigned char *data_ptr = (unsigned char *)(base + NSP_MMIO_OFFSET + DATAREG);
|
||||
|
||||
writeb((unsigned char)reg, index_ptr);
|
||||
return readb(data_ptr);
|
||||
}
|
||||
|
||||
static inline void nsp_mmio_index_write(unsigned long base,
|
||||
unsigned int reg,
|
||||
unsigned char val)
|
||||
{
|
||||
unsigned char *index_ptr = (unsigned char *)(base + NSP_MMIO_OFFSET + INDEXREG);
|
||||
unsigned char *data_ptr = (unsigned char *)(base + NSP_MMIO_OFFSET + DATAREG);
|
||||
|
||||
writeb((unsigned char)reg, index_ptr);
|
||||
writeb(val, data_ptr);
|
||||
}
|
||||
|
||||
/* read 32bit FIFO */
|
||||
static inline void nsp_mmio_multi_read_4(unsigned long base,
|
||||
unsigned int Register,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
unsigned long *ptr = (unsigned long *)(base + Register);
|
||||
unsigned long *tmp = (unsigned long *)buf;
|
||||
int i;
|
||||
|
||||
//nsp_dbg(NSP_DEBUG_DATA_IO, "base 0x%0lx ptr 0x%p",base,ptr);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
*tmp = readl(ptr);
|
||||
//nsp_dbg(NSP_DEBUG_DATA_IO, "<%d,%p,%p,%lx>", i, ptr, tmp, *tmp);
|
||||
tmp++;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void nsp_mmio_fifo32_read(unsigned int base,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
//nsp_dbg(NSP_DEBUG_DATA_IO, "buf=0x%p, count=0x%lx*4", buf, count);
|
||||
nsp_mmio_multi_read_4(base, FIFODATA, buf, count);
|
||||
}
|
||||
|
||||
static inline void nsp_mmio_multi_write_4(unsigned long base,
|
||||
unsigned int Register,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
unsigned long *ptr = (unsigned long *)(base + Register);
|
||||
unsigned long *tmp = (unsigned long *)buf;
|
||||
int i;
|
||||
|
||||
//nsp_dbg(NSP_DEBUG_DATA_IO, "base 0x%0lx ptr 0x%p",base,ptr);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
writel(*tmp, ptr);
|
||||
//nsp_dbg(NSP_DEBUG_DATA_IO, "<%d,%p,%p,%lx>", i, ptr, tmp, *tmp);
|
||||
tmp++;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void nsp_mmio_fifo32_write(unsigned int base,
|
||||
void *buf,
|
||||
unsigned long count)
|
||||
{
|
||||
//nsp_dbg(NSP_DEBUG_DATA_IO, "buf=0x%p, count=0x%lx*4", buf, count);
|
||||
nsp_mmio_multi_write_4(base, FIFODATA, buf, count);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
/* end */
|
||||
78
drivers/scsi/pcmcia/nsp_message.c
Normal file
78
drivers/scsi/pcmcia/nsp_message.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/*==========================================================================
|
||||
NinjaSCSI-3 message handler
|
||||
By: YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>
|
||||
|
||||
This software may be used and distributed according to the terms of
|
||||
the GNU General Public License.
|
||||
*/
|
||||
|
||||
/* $Id: nsp_message.c,v 1.6 2003/07/26 14:21:09 elca Exp $ */
|
||||
|
||||
static void nsp_message_in(Scsi_Cmnd *SCpnt)
|
||||
{
|
||||
unsigned int base = SCpnt->device->host->io_port;
|
||||
nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
|
||||
unsigned char data_reg, control_reg;
|
||||
int ret, len;
|
||||
|
||||
/*
|
||||
* XXX: NSP QUIRK
|
||||
* NSP invoke interrupts only in the case of scsi phase changes,
|
||||
* therefore we should poll the scsi phase here to catch
|
||||
* the next "msg in" if exists (no scsi phase changes).
|
||||
*/
|
||||
ret = 16;
|
||||
len = 0;
|
||||
|
||||
nsp_dbg(NSP_DEBUG_MSGINOCCUR, "msgin loop");
|
||||
do {
|
||||
/* read data */
|
||||
data_reg = nsp_index_read(base, SCSIDATAIN);
|
||||
|
||||
/* assert ACK */
|
||||
control_reg = nsp_index_read(base, SCSIBUSCTRL);
|
||||
control_reg |= SCSI_ACK;
|
||||
nsp_index_write(base, SCSIBUSCTRL, control_reg);
|
||||
nsp_negate_signal(SCpnt, BUSMON_REQ, "msgin<REQ>");
|
||||
|
||||
data->MsgBuffer[len] = data_reg; len++;
|
||||
|
||||
/* deassert ACK */
|
||||
control_reg = nsp_index_read(base, SCSIBUSCTRL);
|
||||
control_reg &= ~SCSI_ACK;
|
||||
nsp_index_write(base, SCSIBUSCTRL, control_reg);
|
||||
|
||||
/* catch a next signal */
|
||||
ret = nsp_expect_signal(SCpnt, BUSPHASE_MESSAGE_IN, BUSMON_REQ);
|
||||
} while (ret > 0 && MSGBUF_SIZE > len);
|
||||
|
||||
data->MsgLen = len;
|
||||
|
||||
}
|
||||
|
||||
static void nsp_message_out(Scsi_Cmnd *SCpnt)
|
||||
{
|
||||
nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
|
||||
int ret = 1;
|
||||
int len = data->MsgLen;
|
||||
|
||||
/*
|
||||
* XXX: NSP QUIRK
|
||||
* NSP invoke interrupts only in the case of scsi phase changes,
|
||||
* therefore we should poll the scsi phase here to catch
|
||||
* the next "msg out" if exists (no scsi phase changes).
|
||||
*/
|
||||
|
||||
nsp_dbg(NSP_DEBUG_MSGOUTOCCUR, "msgout loop");
|
||||
do {
|
||||
if (nsp_xfer(SCpnt, BUSPHASE_MESSAGE_OUT)) {
|
||||
nsp_msg(KERN_DEBUG, "msgout: xfer short");
|
||||
}
|
||||
|
||||
/* catch a next signal */
|
||||
ret = nsp_expect_signal(SCpnt, BUSPHASE_MESSAGE_OUT, BUSMON_REQ);
|
||||
} while (ret > 0 && len-- > 0);
|
||||
|
||||
}
|
||||
|
||||
/* end */
|
||||
425
drivers/scsi/pcmcia/qlogic_stub.c
Normal file
425
drivers/scsi/pcmcia/qlogic_stub.c
Normal file
@@ -0,0 +1,425 @@
|
||||
/*======================================================================
|
||||
|
||||
A driver for the Qlogic SCSI card
|
||||
|
||||
qlogic_cs.c 1.79 2000/06/12 21:27:26
|
||||
|
||||
The contents of this file are subject to the Mozilla Public
|
||||
License Version 1.1 (the "License"); you may not use this file
|
||||
except in compliance with the License. You may obtain a copy of
|
||||
the License at http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS
|
||||
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
rights and limitations under the License.
|
||||
|
||||
The initial developer of the original code is David A. Hinds
|
||||
<dahinds@users.sourceforge.net>. Portions created by David A. Hinds
|
||||
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
|
||||
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
|
||||
by deleting the provisions above and replace them with the notice
|
||||
and other provisions required by the GPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this
|
||||
file under either the MPL or the GPL.
|
||||
|
||||
======================================================================*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <asm/io.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <scsi/scsi_ioctl.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
#include "../qlogicfas408.h"
|
||||
|
||||
#include <pcmcia/version.h>
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ds.h>
|
||||
#include <pcmcia/ciscode.h>
|
||||
|
||||
/* Set the following to 2 to use normal interrupt (active high/totempole-
|
||||
* tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open
|
||||
* drain
|
||||
*/
|
||||
#define INT_TYPE 0
|
||||
|
||||
static char qlogic_name[] = "qlogic_cs";
|
||||
|
||||
#ifdef PCMCIA_DEBUG
|
||||
static int pc_debug = PCMCIA_DEBUG;
|
||||
module_param(pc_debug, int, 0644);
|
||||
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
|
||||
static char *version = "qlogic_cs.c 1.79-ac 2002/10/26 (David Hinds)";
|
||||
#else
|
||||
#define DEBUG(n, args...)
|
||||
#endif
|
||||
|
||||
static Scsi_Host_Template qlogicfas_driver_template = {
|
||||
.module = THIS_MODULE,
|
||||
.name = qlogic_name,
|
||||
.proc_name = qlogic_name,
|
||||
.info = qlogicfas408_info,
|
||||
.queuecommand = qlogicfas408_queuecommand,
|
||||
.eh_abort_handler = qlogicfas408_abort,
|
||||
.eh_bus_reset_handler = qlogicfas408_bus_reset,
|
||||
.eh_device_reset_handler= qlogicfas408_device_reset,
|
||||
.eh_host_reset_handler = qlogicfas408_host_reset,
|
||||
.bios_param = qlogicfas408_biosparam,
|
||||
.can_queue = 1,
|
||||
.this_id = -1,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.cmd_per_lun = 1,
|
||||
.use_clustering = DISABLE_CLUSTERING,
|
||||
};
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
typedef struct scsi_info_t {
|
||||
dev_link_t link;
|
||||
dev_node_t node;
|
||||
struct Scsi_Host *host;
|
||||
unsigned short manf_id;
|
||||
} scsi_info_t;
|
||||
|
||||
static void qlogic_release(dev_link_t *link);
|
||||
static int qlogic_event(event_t event, int priority, event_callback_args_t * args);
|
||||
|
||||
static dev_link_t *qlogic_attach(void);
|
||||
static void qlogic_detach(dev_link_t *);
|
||||
|
||||
|
||||
static dev_link_t *dev_list = NULL;
|
||||
|
||||
static dev_info_t dev_info = "qlogic_cs";
|
||||
|
||||
static struct Scsi_Host *qlogic_detect(Scsi_Host_Template *host,
|
||||
dev_link_t *link, int qbase, int qlirq)
|
||||
{
|
||||
int qltyp; /* type of chip */
|
||||
int qinitid;
|
||||
struct Scsi_Host *shost; /* registered host structure */
|
||||
struct qlogicfas408_priv *priv;
|
||||
|
||||
qltyp = qlogicfas408_get_chip_type(qbase, INT_TYPE);
|
||||
qinitid = host->this_id;
|
||||
if (qinitid < 0)
|
||||
qinitid = 7; /* if no ID, use 7 */
|
||||
|
||||
qlogicfas408_setup(qbase, qinitid, INT_TYPE);
|
||||
|
||||
host->name = qlogic_name;
|
||||
shost = scsi_host_alloc(host, sizeof(struct qlogicfas408_priv));
|
||||
if (!shost)
|
||||
goto err;
|
||||
shost->io_port = qbase;
|
||||
shost->n_io_port = 16;
|
||||
shost->dma_channel = -1;
|
||||
if (qlirq != -1)
|
||||
shost->irq = qlirq;
|
||||
|
||||
priv = get_priv_by_host(shost);
|
||||
priv->qlirq = qlirq;
|
||||
priv->qbase = qbase;
|
||||
priv->qinitid = qinitid;
|
||||
priv->shost = shost;
|
||||
priv->int_type = INT_TYPE;
|
||||
|
||||
if (request_irq(qlirq, qlogicfas408_ihandl, 0, qlogic_name, shost))
|
||||
goto free_scsi_host;
|
||||
|
||||
sprintf(priv->qinfo,
|
||||
"Qlogicfas Driver version 0.46, chip %02X at %03X, IRQ %d, TPdma:%d",
|
||||
qltyp, qbase, qlirq, QL_TURBO_PDMA);
|
||||
|
||||
if (scsi_add_host(shost, NULL))
|
||||
goto free_interrupt;
|
||||
|
||||
scsi_scan_host(shost);
|
||||
|
||||
return shost;
|
||||
|
||||
free_interrupt:
|
||||
free_irq(qlirq, shost);
|
||||
|
||||
free_scsi_host:
|
||||
scsi_host_put(shost);
|
||||
|
||||
err:
|
||||
return NULL;
|
||||
}
|
||||
static dev_link_t *qlogic_attach(void)
|
||||
{
|
||||
scsi_info_t *info;
|
||||
client_reg_t client_reg;
|
||||
dev_link_t *link;
|
||||
int ret;
|
||||
|
||||
DEBUG(0, "qlogic_attach()\n");
|
||||
|
||||
/* Create new SCSI device */
|
||||
info = kmalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return NULL;
|
||||
memset(info, 0, sizeof(*info));
|
||||
link = &info->link;
|
||||
link->priv = info;
|
||||
link->io.NumPorts1 = 16;
|
||||
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
|
||||
link->io.IOAddrLines = 10;
|
||||
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
|
||||
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
|
||||
link->conf.Attributes = CONF_ENABLE_IRQ;
|
||||
link->conf.Vcc = 50;
|
||||
link->conf.IntType = INT_MEMORY_AND_IO;
|
||||
link->conf.Present = PRESENT_OPTION;
|
||||
|
||||
/* Register with Card Services */
|
||||
link->next = dev_list;
|
||||
dev_list = link;
|
||||
client_reg.dev_info = &dev_info;
|
||||
client_reg.event_handler = &qlogic_event;
|
||||
client_reg.EventMask = CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET | CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
|
||||
client_reg.Version = 0x0210;
|
||||
client_reg.event_callback_args.client_data = link;
|
||||
ret = pcmcia_register_client(&link->handle, &client_reg);
|
||||
if (ret != 0) {
|
||||
cs_error(link->handle, RegisterClient, ret);
|
||||
qlogic_detach(link);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return link;
|
||||
} /* qlogic_attach */
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static void qlogic_detach(dev_link_t * link)
|
||||
{
|
||||
dev_link_t **linkp;
|
||||
|
||||
DEBUG(0, "qlogic_detach(0x%p)\n", link);
|
||||
|
||||
/* Locate device structure */
|
||||
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
|
||||
if (*linkp == link)
|
||||
break;
|
||||
if (*linkp == NULL)
|
||||
return;
|
||||
|
||||
if (link->state & DEV_CONFIG)
|
||||
qlogic_release(link);
|
||||
|
||||
if (link->handle)
|
||||
pcmcia_deregister_client(link->handle);
|
||||
|
||||
/* Unlink device structure, free bits */
|
||||
*linkp = link->next;
|
||||
kfree(link->priv);
|
||||
|
||||
} /* qlogic_detach */
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
#define CS_CHECK(fn, ret) \
|
||||
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
|
||||
|
||||
static void qlogic_config(dev_link_t * link)
|
||||
{
|
||||
client_handle_t handle = link->handle;
|
||||
scsi_info_t *info = link->priv;
|
||||
tuple_t tuple;
|
||||
cisparse_t parse;
|
||||
int i, last_ret, last_fn;
|
||||
unsigned short tuple_data[32];
|
||||
struct Scsi_Host *host;
|
||||
|
||||
DEBUG(0, "qlogic_config(0x%p)\n", link);
|
||||
|
||||
tuple.TupleData = (cisdata_t *) tuple_data;
|
||||
tuple.TupleDataMax = 64;
|
||||
tuple.TupleOffset = 0;
|
||||
tuple.DesiredTuple = CISTPL_CONFIG;
|
||||
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
|
||||
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
|
||||
CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
|
||||
link->conf.ConfigBase = parse.config.base;
|
||||
|
||||
tuple.DesiredTuple = CISTPL_MANFID;
|
||||
if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS))
|
||||
info->manf_id = le16_to_cpu(tuple.TupleData[0]);
|
||||
|
||||
/* Configure card */
|
||||
link->state |= DEV_CONFIG;
|
||||
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
|
||||
while (1) {
|
||||
if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
|
||||
pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
|
||||
goto next_entry;
|
||||
link->conf.ConfigIndex = parse.cftable_entry.index;
|
||||
link->io.BasePort1 = parse.cftable_entry.io.win[0].base;
|
||||
link->io.NumPorts1 = parse.cftable_entry.io.win[0].len;
|
||||
if (link->io.BasePort1 != 0) {
|
||||
i = pcmcia_request_io(handle, &link->io);
|
||||
if (i == CS_SUCCESS)
|
||||
break;
|
||||
}
|
||||
next_entry:
|
||||
CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
|
||||
}
|
||||
|
||||
CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
|
||||
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
|
||||
|
||||
if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
|
||||
/* set ATAcmd */
|
||||
outb(0xb4, link->io.BasePort1 + 0xd);
|
||||
outb(0x24, link->io.BasePort1 + 0x9);
|
||||
outb(0x04, link->io.BasePort1 + 0xd);
|
||||
}
|
||||
|
||||
/* The KXL-810AN has a bigger IO port window */
|
||||
if (link->io.NumPorts1 == 32)
|
||||
host = qlogic_detect(&qlogicfas_driver_template, link,
|
||||
link->io.BasePort1 + 16, link->irq.AssignedIRQ);
|
||||
else
|
||||
host = qlogic_detect(&qlogicfas_driver_template, link,
|
||||
link->io.BasePort1, link->irq.AssignedIRQ);
|
||||
|
||||
if (!host) {
|
||||
printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sprintf(info->node.dev_name, "scsi%d", host->host_no);
|
||||
link->dev = &info->node;
|
||||
info->host = host;
|
||||
|
||||
out:
|
||||
link->state &= ~DEV_CONFIG_PENDING;
|
||||
return;
|
||||
|
||||
cs_failed:
|
||||
cs_error(link->handle, last_fn, last_ret);
|
||||
link->dev = NULL;
|
||||
pcmcia_release_configuration(link->handle);
|
||||
pcmcia_release_io(link->handle, &link->io);
|
||||
pcmcia_release_irq(link->handle, &link->irq);
|
||||
link->state &= ~DEV_CONFIG;
|
||||
return;
|
||||
|
||||
} /* qlogic_config */
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static void qlogic_release(dev_link_t *link)
|
||||
{
|
||||
scsi_info_t *info = link->priv;
|
||||
|
||||
DEBUG(0, "qlogic_release(0x%p)\n", link);
|
||||
|
||||
scsi_remove_host(info->host);
|
||||
link->dev = NULL;
|
||||
|
||||
free_irq(link->irq.AssignedIRQ, info->host);
|
||||
|
||||
pcmcia_release_configuration(link->handle);
|
||||
pcmcia_release_io(link->handle, &link->io);
|
||||
pcmcia_release_irq(link->handle, &link->irq);
|
||||
|
||||
scsi_host_put(info->host);
|
||||
|
||||
link->state &= ~DEV_CONFIG;
|
||||
}
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
static int qlogic_event(event_t event, int priority, event_callback_args_t * args)
|
||||
{
|
||||
dev_link_t *link = args->client_data;
|
||||
|
||||
DEBUG(1, "qlogic_event(0x%06x)\n", event);
|
||||
|
||||
switch (event) {
|
||||
case CS_EVENT_CARD_REMOVAL:
|
||||
link->state &= ~DEV_PRESENT;
|
||||
if (link->state & DEV_CONFIG)
|
||||
qlogic_release(link);
|
||||
break;
|
||||
case CS_EVENT_CARD_INSERTION:
|
||||
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
|
||||
qlogic_config(link);
|
||||
break;
|
||||
case CS_EVENT_PM_SUSPEND:
|
||||
link->state |= DEV_SUSPEND;
|
||||
/* Fall through... */
|
||||
case CS_EVENT_RESET_PHYSICAL:
|
||||
if (link->state & DEV_CONFIG)
|
||||
pcmcia_release_configuration(link->handle);
|
||||
break;
|
||||
case CS_EVENT_PM_RESUME:
|
||||
link->state &= ~DEV_SUSPEND;
|
||||
/* Fall through... */
|
||||
case CS_EVENT_CARD_RESET:
|
||||
if (link->state & DEV_CONFIG) {
|
||||
scsi_info_t *info = link->priv;
|
||||
pcmcia_request_configuration(link->handle, &link->conf);
|
||||
if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
|
||||
outb(0x80, link->io.BasePort1 + 0xd);
|
||||
outb(0x24, link->io.BasePort1 + 0x9);
|
||||
outb(0x04, link->io.BasePort1 + 0xd);
|
||||
}
|
||||
/* Ugggglllyyyy!!! */
|
||||
qlogicfas408_bus_reset(NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
} /* qlogic_event */
|
||||
|
||||
|
||||
static struct pcmcia_driver qlogic_cs_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.drv = {
|
||||
.name = "qlogic_cs",
|
||||
},
|
||||
.attach = qlogic_attach,
|
||||
.detach = qlogic_detach,
|
||||
};
|
||||
|
||||
static int __init init_qlogic_cs(void)
|
||||
{
|
||||
return pcmcia_register_driver(&qlogic_cs_driver);
|
||||
}
|
||||
|
||||
static void __exit exit_qlogic_cs(void)
|
||||
{
|
||||
pcmcia_unregister_driver(&qlogic_cs_driver);
|
||||
BUG_ON(dev_list != NULL);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Tom Zerucha, Michael Griffith");
|
||||
MODULE_DESCRIPTION("Driver for the PCMCIA Qlogic FAS SCSI controllers");
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init(init_qlogic_cs);
|
||||
module_exit(exit_qlogic_cs);
|
||||
1022
drivers/scsi/pcmcia/sym53c500_cs.c
Normal file
1022
drivers/scsi/pcmcia/sym53c500_cs.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user