***********************************************************************/
-/* $Id: nsp_cs.c,v 1.23 2003/08/18 11:09:19 elca Exp $ */
-
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include "nsp_cs.h"
MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>");
-MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module $Revision: 1.23 $");
+MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module");
MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
module_param(free_ports, bool, 0);
MODULE_PARM_DESC(free_ports, "Release IO ports after configuration? (default: 0 (=no))");
-/* /usr/src/linux/drivers/scsi/hosts.h */
static struct scsi_host_template nsp_driver_template = {
.proc_name = "nsp_cs",
.proc_info = nsp_proc_info,
.name = "WorkBit NinjaSCSI-3/32Bi(16bit)",
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
- .detect = nsp_detect_old,
- .release = nsp_release_old,
-#endif
.info = nsp_info,
.queuecommand = nsp_queuecommand,
/* .eh_abort_handler = nsp_eh_abort,*/
.sg_tablesize = SG_ALL,
.cmd_per_lun = 1,
.use_clustering = DISABLE_CLUSTERING,
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2))
- .use_new_eh_code = 1,
-#endif
};
static nsp_hw_data nsp_data_base; /* attach <-> detect glue */
#else
# define NSP_DEBUG_MASK 0xffffff
# define nsp_msg(type, args...) \
- nsp_cs_message (__FUNCTION__, __LINE__, (type), args)
+ nsp_cs_message (__func__, __LINE__, (type), args)
# define nsp_dbg(mask, args...) \
- nsp_cs_dmessage(__FUNCTION__, __LINE__, (mask), args)
+ nsp_cs_dmessage(__func__, __LINE__, (mask), args)
#endif
#define NSP_DEBUG_QUEUECOMMAND BIT(0)
#define NSP_DEBUG_BUF_LEN 150
+static inline void nsp_inc_resid(struct scsi_cmnd *SCpnt, int residInc)
+{
+ scsi_set_resid(SCpnt, scsi_get_resid(SCpnt) + residInc);
+}
+
static void nsp_cs_message(const char *func, int line, char *type, char *fmt, ...)
{
va_list args;
* Clenaup parameters and call done() functions.
* You must be set SCpnt->result before call this function.
*/
-static void nsp_scsi_done(Scsi_Cmnd *SCpnt)
+static void nsp_scsi_done(struct scsi_cmnd *SCpnt)
{
nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
SCpnt->scsi_done(SCpnt);
}
-static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+static int nsp_queuecommand(struct scsi_cmnd *SCpnt,
+ void (*done)(struct scsi_cmnd *))
{
#ifdef NSP_DEBUG
/*unsigned int host_id = SCpnt->device->host->this_id;*/
#endif
nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
- nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "SCpnt=0x%p target=%d lun=%d buff=0x%p bufflen=%d use_sg=%d",
- SCpnt, target, SCpnt->device->lun, SCpnt->request_buffer, SCpnt->request_bufflen, SCpnt->use_sg);
+ nsp_dbg(NSP_DEBUG_QUEUECOMMAND,
+ "SCpnt=0x%p target=%d lun=%d sglist=0x%p bufflen=%d sg_count=%d",
+ SCpnt, target, SCpnt->device->lun, scsi_sglist(SCpnt),
+ scsi_bufflen(SCpnt), scsi_sg_count(SCpnt));
//nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "before CurrentSC=0x%p", data->CurrentSC);
SCpnt->scsi_done = done;
SCpnt->SCp.have_data_in = IO_UNKNOWN;
SCpnt->SCp.sent_command = 0;
SCpnt->SCp.phase = PH_UNDETERMINED;
- SCpnt->resid = SCpnt->request_bufflen;
+ scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
/* setup scratch area
SCp.ptr : buffer pointer
SCp.buffer : next buffer
SCp.buffers_residual : left buffers in list
SCp.phase : current state of the command */
- if (SCpnt->use_sg) {
- SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->request_buffer;
+ if (scsi_bufflen(SCpnt)) {
+ SCpnt->SCp.buffer = scsi_sglist(SCpnt);
SCpnt->SCp.ptr = BUFFER_ADDR;
SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
- SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
+ SCpnt->SCp.buffers_residual = scsi_sg_count(SCpnt) - 1;
} else {
- SCpnt->SCp.ptr = (char *) SCpnt->request_buffer;
- SCpnt->SCp.this_residual = SCpnt->request_bufflen;
+ SCpnt->SCp.ptr = NULL;
+ SCpnt->SCp.this_residual = 0;
SCpnt->SCp.buffer = NULL;
SCpnt->SCp.buffers_residual = 0;
}
/*
* Start selection phase
*/
-static int nsphw_start_selection(Scsi_Cmnd *SCpnt)
+static int nsphw_start_selection(struct scsi_cmnd *SCpnt)
{
unsigned int host_id = SCpnt->device->host->this_id;
unsigned int base = SCpnt->device->host->io_port;
/*
* setup synchronous data transfer mode
*/
-static int nsp_analyze_sdtr(Scsi_Cmnd *SCpnt)
+static int nsp_analyze_sdtr(struct scsi_cmnd *SCpnt)
{
unsigned char target = scmd_id(SCpnt);
// unsigned char lun = SCpnt->device->lun;
/*
* start ninja hardware timer
*/
-static void nsp_start_timer(Scsi_Cmnd *SCpnt, int time)
+static void nsp_start_timer(struct scsi_cmnd *SCpnt, int time)
{
unsigned int base = SCpnt->device->host->io_port;
nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
/*
* wait for bus phase change
*/
-static int nsp_negate_signal(Scsi_Cmnd *SCpnt, unsigned char mask, char *str)
+static int nsp_negate_signal(struct scsi_cmnd *SCpnt, unsigned char mask,
+ char *str)
{
unsigned int base = SCpnt->device->host->io_port;
unsigned char reg;
/*
* expect Ninja Irq
*/
-static int nsp_expect_signal(Scsi_Cmnd *SCpnt,
- unsigned char current_phase,
- unsigned char mask)
+static int nsp_expect_signal(struct scsi_cmnd *SCpnt,
+ unsigned char current_phase,
+ unsigned char mask)
{
unsigned int base = SCpnt->device->host->io_port;
int time_out;
/*
* transfer SCSI message
*/
-static int nsp_xfer(Scsi_Cmnd *SCpnt, int phase)
+static int nsp_xfer(struct scsi_cmnd *SCpnt, int phase)
{
unsigned int base = SCpnt->device->host->io_port;
nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
/*
* get extra SCSI data from fifo
*/
-static int nsp_dataphase_bypass(Scsi_Cmnd *SCpnt)
+static int nsp_dataphase_bypass(struct scsi_cmnd *SCpnt)
{
nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
unsigned int count;
/*
* accept reselection
*/
-static int nsp_reselected(Scsi_Cmnd *SCpnt)
+static int nsp_reselected(struct scsi_cmnd *SCpnt)
{
unsigned int base = SCpnt->device->host->io_port;
unsigned int host_id = SCpnt->device->host->this_id;
/*
* count how many data transferd
*/
-static int nsp_fifo_count(Scsi_Cmnd *SCpnt)
+static int nsp_fifo_count(struct scsi_cmnd *SCpnt)
{
unsigned int base = SCpnt->device->host->io_port;
unsigned int count;
/*
* read data in DATA IN phase
*/
-static void nsp_pio_read(Scsi_Cmnd *SCpnt)
+static void nsp_pio_read(struct scsi_cmnd *SCpnt)
{
unsigned int base = SCpnt->device->host->io_port;
unsigned long mmio_base = SCpnt->device->host->base;
ocount = data->FifoCount;
nsp_dbg(NSP_DEBUG_DATA_IO, "in SCpnt=0x%p resid=%d ocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d",
- SCpnt, SCpnt->resid, ocount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual);
+ SCpnt, scsi_get_resid(SCpnt), ocount, SCpnt->SCp.ptr,
+ SCpnt->SCp.this_residual, SCpnt->SCp.buffer,
+ SCpnt->SCp.buffers_residual);
time_out = 1000;
return;
}
- SCpnt->resid -= res;
+ nsp_inc_resid(SCpnt, -res);
SCpnt->SCp.ptr += res;
SCpnt->SCp.this_residual -= res;
ocount += res;
if (time_out == 0) {
nsp_msg(KERN_DEBUG, "pio read timeout resid=%d this_residual=%d buffers_residual=%d",
- SCpnt->resid, SCpnt->SCp.this_residual, SCpnt->SCp.buffers_residual);
+ scsi_get_resid(SCpnt), SCpnt->SCp.this_residual,
+ SCpnt->SCp.buffers_residual);
}
nsp_dbg(NSP_DEBUG_DATA_IO, "read ocount=0x%x", ocount);
- nsp_dbg(NSP_DEBUG_DATA_IO, "r cmd=%d resid=0x%x\n", data->CmdId, SCpnt->resid);
+ nsp_dbg(NSP_DEBUG_DATA_IO, "r cmd=%d resid=0x%x\n", data->CmdId,
+ scsi_get_resid(SCpnt));
}
/*
* write data in DATA OUT phase
*/
-static void nsp_pio_write(Scsi_Cmnd *SCpnt)
+static void nsp_pio_write(struct scsi_cmnd *SCpnt)
{
unsigned int base = SCpnt->device->host->io_port;
unsigned long mmio_base = SCpnt->device->host->base;
ocount = data->FifoCount;
nsp_dbg(NSP_DEBUG_DATA_IO, "in fifocount=%d ptr=0x%p this_residual=%d buffers=0x%p nbuf=%d resid=0x%x",
- data->FifoCount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual, SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual, SCpnt->resid);
+ data->FifoCount, SCpnt->SCp.ptr, SCpnt->SCp.this_residual,
+ SCpnt->SCp.buffer, SCpnt->SCp.buffers_residual,
+ scsi_get_resid(SCpnt));
time_out = 1000;
nsp_dbg(NSP_DEBUG_DATA_IO, "phase changed stat=0x%x, res=%d\n", stat, res);
/* Put back pointer */
- SCpnt->resid += res;
+ nsp_inc_resid(SCpnt, res);
SCpnt->SCp.ptr -= res;
SCpnt->SCp.this_residual += res;
ocount -= res;
break;
}
- SCpnt->resid -= res;
+ nsp_inc_resid(SCpnt, -res);
SCpnt->SCp.ptr += res;
SCpnt->SCp.this_residual -= res;
ocount += res;
data->FifoCount = ocount;
if (time_out == 0) {
- nsp_msg(KERN_DEBUG, "pio write timeout resid=0x%x", SCpnt->resid);
+ nsp_msg(KERN_DEBUG, "pio write timeout resid=0x%x",
+ scsi_get_resid(SCpnt));
}
nsp_dbg(NSP_DEBUG_DATA_IO, "write ocount=0x%x", ocount);
- nsp_dbg(NSP_DEBUG_DATA_IO, "w cmd=%d resid=0x%x\n", data->CmdId, SCpnt->resid);
+ nsp_dbg(NSP_DEBUG_DATA_IO, "w cmd=%d resid=0x%x\n", data->CmdId,
+ scsi_get_resid(SCpnt));
}
#undef RFIFO_CRIT
#undef WFIFO_CRIT
/*
* setup synchronous/asynchronous data transfer mode
*/
-static int nsp_nexus(Scsi_Cmnd *SCpnt)
+static int nsp_nexus(struct scsi_cmnd *SCpnt)
{
unsigned int base = SCpnt->device->host->io_port;
unsigned char target = scmd_id(SCpnt);
nsp_index_write(base, SYNCREG, sync->SyncRegister);
nsp_index_write(base, ACKWIDTH, sync->AckWidth);
- if (SCpnt->use_sg == 0 ||
- SCpnt->resid % 4 != 0 ||
- SCpnt->resid <= PAGE_SIZE ) {
+ if (scsi_get_resid(SCpnt) % 4 != 0 ||
+ scsi_get_resid(SCpnt) <= PAGE_SIZE ) {
data->TransferMode = MODE_IO8;
} else if (nsp_burst_mode == BURST_MEM32) {
data->TransferMode = MODE_MEM32;
/*
* interrupt handler
*/
-static irqreturn_t nspintr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t nspintr(int irq, void *dev_id)
{
unsigned int base;
unsigned char irq_status, irq_phase, phase;
- Scsi_Cmnd *tmpSC;
+ struct scsi_cmnd *tmpSC;
unsigned char target, lun;
unsigned int *sync_neg;
int i, tmp;
nsp_hw_data *data_b = &nsp_data_base, *data;
nsp_dbg(NSP_DEBUG_INIT, "this_id=%d", sht->this_id);
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
host = scsi_host_alloc(&nsp_driver_template, sizeof(nsp_hw_data));
-#else
- host = scsi_register(sht, sizeof(nsp_hw_data));
-#endif
if (host == NULL) {
nsp_dbg(NSP_DEBUG_INIT, "host failed");
return NULL;
return host; /* detect done. */
}
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
-static int nsp_detect_old(struct scsi_host_template *sht)
-{
- if (nsp_detect(sht) == NULL) {
- return 0;
- } else {
- //MOD_INC_USE_COUNT;
- return 1;
- }
-}
-
-
-static int nsp_release_old(struct Scsi_Host *shpnt)
-{
- //nsp_hw_data *data = (nsp_hw_data *)shpnt->hostdata;
-
- /* PCMCIA Card Service dose same things below. */
- /* So we do nothing. */
- //if (shpnt->irq) {
- // free_irq(shpnt->irq, data->ScsiInfo);
- //}
- //if (shpnt->io_port) {
- // release_region(shpnt->io_port, shpnt->n_io_port);
- //}
-
- //MOD_DEC_USE_COUNT;
-
- return 0;
-}
-#endif
-
/*----------------------------------------------------------------*/
/* return info string */
/*----------------------------------------------------------------*/
nsp_dbg(NSP_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length, length - (pos - buffer));\
} \
} while(0)
-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_proc_info(struct Scsi_Host *host, char *buffer, char **start,
+ off_t offset, int length, int inout)
{
int id;
char *pos = buffer;
int speed;
unsigned long flags;
nsp_hw_data *data;
-#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
- struct Scsi_Host *host;
-#else
int hostno;
-#endif
+
if (inout) {
return -EINVAL;
}
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73))
hostno = host->host_no;
-#else
- /* search this HBA host */
- host = scsi_host_hn_get(hostno);
- if (host == NULL) {
- return -ESRCH;
- }
-#endif
data = (nsp_hw_data *)host->hostdata;
/*---------------------------------------------------------------*/
/*
-static int nsp_eh_abort(Scsi_Cmnd *SCpnt)
+static int nsp_eh_abort(struct scsi_cmnd *SCpnt)
{
nsp_dbg(NSP_DEBUG_BUSRESET, "SCpnt=0x%p", SCpnt);
return SUCCESS;
}
-static int nsp_eh_bus_reset(Scsi_Cmnd *SCpnt)
+static int nsp_eh_bus_reset(struct scsi_cmnd *SCpnt)
{
nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
return nsp_bus_reset(data);
}
-static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt)
+static int nsp_eh_host_reset(struct scsi_cmnd *SCpnt)
{
nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata;
configure the card at this point -- we wait until we receive a
card insertion event.
======================================================================*/
-static int nsp_cs_attach(struct pcmcia_device *p_dev)
+static int nsp_cs_probe(struct pcmcia_device *link)
{
scsi_info_t *info;
- dev_link_t *link;
nsp_hw_data *data = &nsp_data_base;
+ int ret;
nsp_dbg(NSP_DEBUG_INIT, "in");
/* Create new SCSI device */
- info = kmalloc(sizeof(*info), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (info == NULL) { return -ENOMEM; }
- memset(info, 0, sizeof(*info));
- link = &info->link;
+ info->p_dev = link;
link->priv = info;
data->ScsiInfo = info;
/* Interrupt handler */
link->irq.Handler = &nspintr;
link->irq.Instance = info;
- link->irq.Attributes |= (SA_SHIRQ | SA_SAMPLE_RANDOM);
+ link->irq.Attributes |= IRQF_SHARED;
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.Present = PRESENT_OPTION;
-
- link->handle = p_dev;
- p_dev->instance = link;
- link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
- nsp_cs_config(link);
+ ret = nsp_cs_config(link);
nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
- return 0;
+ return ret;
} /* nsp_cs_attach */
structures are freed. Otherwise, the structures will be freed
when the device is released.
======================================================================*/
-static void nsp_cs_detach(struct pcmcia_device *p_dev)
+static void nsp_cs_detach(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(p_dev);
-
nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
- if (link->state & DEV_CONFIG) {
- ((scsi_info_t *)link->priv)->stop = 1;
- nsp_cs_release(link);
- }
+ ((scsi_info_t *)link->priv)->stop = 1;
+ nsp_cs_release(link);
kfree(link->priv);
link->priv = NULL;
is received, to configure the PCMCIA socket, and to make the
ethernet device available to the system.
======================================================================*/
-#define CS_CHECK(fn, ret) \
-do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
-/*====================================================================*/
-static void nsp_cs_config(dev_link_t *link)
+
+struct nsp_cs_configdata {
+ nsp_hw_data *data;
+ win_req_t req;
+};
+
+static int nsp_cs_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- client_handle_t handle = link->handle;
- scsi_info_t *info = link->priv;
- tuple_t tuple;
- cisparse_t parse;
- int last_ret, last_fn;
- unsigned char tuple_data[64];
- config_info_t conf;
- win_req_t req;
- memreq_t map;
- cistpl_cftable_entry_t dflt = { 0 };
- struct Scsi_Host *host;
- nsp_hw_data *data = &nsp_data_base;
-#if !(LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
- struct scsi_device *dev;
- dev_node_t **tail, *node;
-#endif
+ struct nsp_cs_configdata *cfg_mem = priv_data;
- nsp_dbg(NSP_DEBUG_INIT, "in");
+ if (cfg->index == 0)
+ return -ENODEV;
- tuple.DesiredTuple = CISTPL_CONFIG;
- tuple.Attributes = 0;
- tuple.TupleData = tuple_data;
- tuple.TupleDataMax = sizeof(tuple_data);
- 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;
- link->conf.Present = parse.config.rmask[0];
-
- /* Configure card */
- link->state |= DEV_CONFIG;
-
- /* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf));
-
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
- while (1) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-
- if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
- pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
- goto next_entry;
-
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { dflt = *cfg; }
- if (cfg->index == 0) { goto next_entry; }
- link->conf.ConfigIndex = cfg->index;
-
- /* Does this card need audio output? */
- if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
- link->conf.Attributes |= CONF_ENABLE_SPKR;
- link->conf.Status = CCSR_AUDIO_ENA;
- }
+ /* Does this card need audio output? */
+ if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
+ p_dev->conf.Attributes |= CONF_ENABLE_SPKR;
+ p_dev->conf.Status = CCSR_AUDIO_ENA;
+ }
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
- if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) {
- goto next_entry;
- }
- } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
- if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) {
- goto next_entry;
- }
+ /* Use power settings for Vcc and Vpp if present */
+ /* Note that the CIS values need to be rescaled */
+ if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+ if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
+ return -ENODEV;
+ else if (dflt->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+ if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM]/10000)
+ return -ENODEV;
}
if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
- link->conf.Vpp =
+ p_dev->conf.Vpp =
cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- } else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) {
- link->conf.Vpp =
- dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ } else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) {
+ p_dev->conf.Vpp =
+ dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
}
/* Do we need to allocate an interrupt? */
- if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) {
- link->conf.Attributes |= CONF_ENABLE_IRQ;
- }
+ if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1)
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
/* IO window settings */
- link->io.NumPorts1 = link->io.NumPorts2 = 0;
- if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+ p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
if (!(io->flags & CISTPL_IO_8BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
if (!(io->flags & CISTPL_IO_16BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- link->io.BasePort1 = io->win[0].base;
- link->io.NumPorts1 = io->win[0].len;
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ p_dev->io.BasePort1 = io->win[0].base;
+ p_dev->io.NumPorts1 = io->win[0].len;
if (io->nwin > 1) {
- link->io.Attributes2 = link->io.Attributes1;
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = io->win[1].len;
+ p_dev->io.Attributes2 = p_dev->io.Attributes1;
+ p_dev->io.BasePort2 = io->win[1].base;
+ p_dev->io.NumPorts2 = io->win[1].len;
}
/* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link->handle, &link->io) != 0)
+ if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
goto next_entry;
}
- if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
- cistpl_mem_t *mem =
- (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
- req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
- req.Attributes |= WIN_ENABLE;
- req.Base = mem->win[0].host_addr;
- req.Size = mem->win[0].len;
- if (req.Size < 0x1000) {
- req.Size = 0x1000;
- }
- req.AccessSpeed = 0;
- if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
+ if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
+ memreq_t map;
+ cistpl_mem_t *mem =
+ (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+ cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
+ cfg_mem->req.Attributes |= WIN_ENABLE;
+ cfg_mem->req.Base = mem->win[0].host_addr;
+ cfg_mem->req.Size = mem->win[0].len;
+ if (cfg_mem->req.Size < 0x1000)
+ cfg_mem->req.Size = 0x1000;
+ cfg_mem->req.AccessSpeed = 0;
+ if (pcmcia_request_window(&p_dev, &cfg_mem->req, &p_dev->win) != 0)
goto next_entry;
map.Page = 0; map.CardOffset = mem->win[0].card_addr;
- if (pcmcia_map_mem_page(link->win, &map) != 0)
+ if (pcmcia_map_mem_page(p_dev->win, &map) != 0)
goto next_entry;
- data->MmioAddress = (unsigned long)ioremap_nocache(req.Base, req.Size);
- data->MmioLength = req.Size;
+ cfg_mem->data->MmioAddress = (unsigned long) ioremap_nocache(cfg_mem->req.Base, cfg_mem->req.Size);
+ cfg_mem->data->MmioLength = cfg_mem->req.Size;
}
/* If we got this far, we're cool! */
- break;
-
- next_entry:
- nsp_dbg(NSP_DEBUG_INIT, "next");
- pcmcia_disable_device(handle);
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
+ return 0;
}
+next_entry:
+ nsp_dbg(NSP_DEBUG_INIT, "next");
+ pcmcia_disable_device(p_dev);
+ return -ENODEV;
+}
+
+static int nsp_cs_config(struct pcmcia_device *link)
+{
+ int ret;
+ scsi_info_t *info = link->priv;
+ struct nsp_cs_configdata *cfg_mem;
+ struct Scsi_Host *host;
+ nsp_hw_data *data = &nsp_data_base;
+
+ nsp_dbg(NSP_DEBUG_INIT, "in");
+
+ cfg_mem = kzalloc(sizeof(cfg_mem), GFP_KERNEL);
+ if (!cfg_mem)
+ return -ENOMEM;
+ cfg_mem->data = data;
+
+ ret = pcmcia_loop_config(link, nsp_cs_config_check, cfg_mem);
+ goto cs_failed;
+
if (link->conf.Attributes & CONF_ENABLE_IRQ) {
- CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
+ if (pcmcia_request_irq(link, &link->irq))
+ goto cs_failed;
}
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
+
+ ret = pcmcia_request_configuration(link, &link->conf);
+ if (ret)
+ goto cs_failed;
if (free_ports) {
if (link->io.BasePort1) {
goto cs_failed;
}
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2))
host = nsp_detect(&nsp_driver_template);
-#else
- scsi_register_host(&nsp_driver_template);
- for (host = scsi_host_get_next(NULL); host != NULL;
- host = scsi_host_get_next(host)) {
- if (host->hostt == &nsp_driver_template) {
- break;
- }
- }
-#endif
if (host == NULL) {
nsp_dbg(NSP_DEBUG_INIT, "detect failed");
}
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74))
- scsi_add_host (host, NULL);
+ ret = scsi_add_host (host, NULL);
+ if (ret)
+ goto cs_failed;
+
scsi_scan_host(host);
snprintf(info->node.dev_name, sizeof(info->node.dev_name), "scsi%d", host->host_no);
- link->dev = &info->node;
+ link->dev_node = &info->node;
info->host = host;
-#else
- nsp_dbg(NSP_DEBUG_INIT, "GET_SCSI_INFO");
- tail = &link->dev;
- info->ndev = 0;
-
- nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host);
-
- for (dev = host->host_queue; dev != NULL; dev = dev->next) {
- unsigned long id;
- id = (dev->id & 0x0f) + ((dev->lun & 0x0f) << 4) +
- ((dev->channel & 0x0f) << 8) +
- ((dev->host->host_no & 0x0f) << 12);
- node = &info->node[info->ndev];
- node->minor = 0;
- switch (dev->type) {
- case TYPE_TAPE:
- node->major = SCSI_TAPE_MAJOR;
- snprintf(node->dev_name, sizeof(node->dev_name), "st#%04lx", id);
- break;
- case TYPE_DISK:
- case TYPE_MOD:
- node->major = SCSI_DISK0_MAJOR;
- snprintf(node->dev_name, sizeof(node->dev_name), "sd#%04lx", id);
- break;
- case TYPE_ROM:
- case TYPE_WORM:
- node->major = SCSI_CDROM_MAJOR;
- snprintf(node->dev_name, sizeof(node->dev_name), "sr#%04lx", id);
- break;
- default:
- node->major = SCSI_GENERIC_MAJOR;
- snprintf(node->dev_name, sizeof(node->dev_name), "sg#%04lx", id);
- break;
- }
- *tail = node; tail = &node->next;
- info->ndev++;
- info->host = dev->host;
- }
-
- *tail = NULL;
- if (info->ndev == 0) {
- nsp_msg(KERN_INFO, "no SCSI devices found");
- }
- nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host);
-#endif
-
/* Finally, report what we've done */
printk(KERN_INFO "nsp_cs: index 0x%02x: ",
link->conf.ConfigIndex);
printk(" & 0x%04x-0x%04x", link->io.BasePort2,
link->io.BasePort2+link->io.NumPorts2-1);
if (link->win)
- printk(", mem 0x%06lx-0x%06lx", req.Base,
- req.Base+req.Size-1);
+ printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base,
+ cfg_mem->req.Base+cfg_mem->req.Size-1);
printk("\n");
- link->state &= ~DEV_CONFIG_PENDING;
- return;
+ kfree(cfg_mem);
+ return 0;
cs_failed:
nsp_dbg(NSP_DEBUG_INIT, "config fail");
- cs_error(link->handle, last_fn, last_ret);
nsp_cs_release(link);
+ kfree(cfg_mem);
- return;
+ return -ENODEV;
} /* nsp_cs_config */
-#undef CS_CHECK
/*======================================================================
device, and release the PCMCIA configuration. If the device is
still open, this will be postponed until it is closed.
======================================================================*/
-static void nsp_cs_release(dev_link_t *link)
+static void nsp_cs_release(struct pcmcia_device *link)
{
scsi_info_t *info = link->priv;
nsp_hw_data *data = NULL;
nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
/* Unlink the device chain */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2))
if (info->host != NULL) {
scsi_remove_host(info->host);
}
-#else
- scsi_unregister_host(&nsp_driver_template);
-#endif
- link->dev = NULL;
+ link->dev_node = NULL;
if (link->win) {
if (data != NULL) {
iounmap((void *)(data->MmioAddress));
}
}
- pcmcia_disable_device(link->handle);
+ pcmcia_disable_device(link);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2))
if (info->host != NULL) {
scsi_host_put(info->host);
}
-#endif
} /* nsp_cs_release */
-static int nsp_cs_suspend(struct pcmcia_device *dev)
+static int nsp_cs_suspend(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
scsi_info_t *info = link->priv;
nsp_hw_data *data;
return 0;
}
-static int nsp_cs_resume(struct pcmcia_device *dev)
+static int nsp_cs_resume(struct pcmcia_device *link)
{
- dev_link_t *link = dev_to_instance(dev);
scsi_info_t *info = link->priv;
nsp_hw_data *data;
/*======================================================================*
* module entry point
*====================================================================*/
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
static struct pcmcia_device_id nsp_cs_ids[] = {
PCMCIA_DEVICE_PROD_ID123("IO DATA", "CBSC16 ", "1", 0x547e66dc, 0x0d63a3fd, 0x51de003a),
PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-001", "1", 0x534c02bc, 0x52008408, 0x51de003a),
.drv = {
.name = "nsp_cs",
},
- .probe = nsp_cs_attach,
+ .probe = nsp_cs_probe,
.remove = nsp_cs_detach,
.id_table = nsp_cs_ids,
.suspend = nsp_cs_suspend,
.resume = nsp_cs_resume,
};
-#endif
static int __init nsp_cs_init(void)
{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
nsp_msg(KERN_INFO, "loading...");
return pcmcia_register_driver(&nsp_driver);
-#else
- servinfo_t serv;
-
- nsp_msg(KERN_INFO, "loading...");
- pcmcia_get_card_services_info(&serv);
- if (serv.Revision != CS_RELEASE_CODE) {
- nsp_msg(KERN_DEBUG, "Card Services release does not match!");
- return -EINVAL;
- }
- register_pcmcia_driver(&dev_info, &nsp_cs_attach, &nsp_cs_detach);
-
- nsp_dbg(NSP_DEBUG_INIT, "out");
- return 0;
-#endif
}
static void __exit nsp_cs_exit(void)
{
nsp_msg(KERN_INFO, "unloading...");
-
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
pcmcia_unregister_driver(&nsp_driver);
-#else
- unregister_pcmcia_driver(&dev_info);
- /* XXX: this really needs to move into generic code.. */
- while (dev_list != NULL) {
- if (dev_list->state & DEV_CONFIG) {
- nsp_cs_release(dev_list);
- }
- nsp_cs_detach(dev_list);
- }
-#endif
}