/* ======================== Module parameters ======================== */
-MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>, Jose Orlando Pereira <jop@di.uminho.pt>");
+MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE("BT3CPCC.bin");
kfree(info);
}
- static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+ static int bt3c_check_config(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- int i;
-
- i = pcmcia_get_tuple_data(handle, tuple);
- if (i != CS_SUCCESS)
- return i;
-
- return pcmcia_parse_tuple(handle, tuple, parse);
- }
-
- static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
- {
- if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS)
- return CS_NO_MORE_ITEMS;
- return get_tuple(handle, tuple, parse);
+ unsigned long try = (unsigned long) priv_data;
+
+ if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
+ (cf->io.win[0].base != 0)) {
+ p_dev->io.BasePort1 = cf->io.win[0].base;
+ p_dev->io.IOAddrLines = (try == 0) ? 16 :
+ cf->io.flags & CISTPL_IO_LINES_MASK;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ return -ENODEV;
}
- static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+ static int bt3c_check_config_notpicky(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
{
- if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
- return CS_NO_MORE_ITEMS;
- return get_tuple(handle, tuple, parse);
+ static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+ int j;
+
+ if ((cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
+ for (j = 0; j < 5; j++) {
+ p_dev->io.BasePort1 = base[j];
+ p_dev->io.IOAddrLines = base[j] ? 16 : 3;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ }
+ return -ENODEV;
}
static int bt3c_config(struct pcmcia_device *link)
{
- static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
bt3c_info_t *info = link->priv;
- tuple_t tuple;
- u_short buf[256];
- cisparse_t parse;
- cistpl_cftable_entry_t *cf = &parse.cftable_entry;
- int i, j, try;
-
- /* First pass: look for a config entry that looks normal. */
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleOffset = 0;
- tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- /* Two tries: without IO aliases, then with aliases */
- for (try = 0; try < 2; try++) {
- i = first_tuple(link, &tuple, &parse);
- while (i != CS_NO_MORE_ITEMS) {
- if (i != CS_SUCCESS)
- goto next_entry;
- if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) {
- link->conf.ConfigIndex = cf->index;
- link->io.BasePort1 = cf->io.win[0].base;
- link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
- goto found_port;
- }
- next_entry:
- i = next_tuple(link, &tuple, &parse);
- }
- }
+ int i;
+ unsigned long try;
+
+ /* First pass: look for a config entry that looks normal.
+ Two tries: without IO aliases, then with aliases */
+ for (try = 0; try < 2; try++)
+ if (!pcmcia_loop_config(link, bt3c_check_config, (void *) try))
+ goto found_port;
/* Second pass: try to find an entry that isn't picky about
its base address, then try to grab any standard serial port
address, and finally try to get any free port. */
- i = first_tuple(link, &tuple, &parse);
- while (i != CS_NO_MORE_ITEMS) {
- if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
- link->conf.ConfigIndex = cf->index;
- for (j = 0; j < 5; j++) {
- link->io.BasePort1 = base[j];
- link->io.IOAddrLines = base[j] ? 16 : 3;
- i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
- goto found_port;
- }
- }
- i = next_tuple(link, &tuple, &parse);
- }
+ if (!pcmcia_loop_config(link, bt3c_check_config_notpicky, NULL))
+ goto found_port;
- found_port:
- if (i != CS_SUCCESS) {
- BT_ERR("No usable port range found");
- cs_error(link, RequestIO, i);
- goto failed;
- }
+ BT_ERR("No usable port range found");
+ cs_error(link, RequestIO, -ENODEV);
+ goto failed;
+ found_port:
i = pcmcia_request_irq(link, &link->irq);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIRQ, i);
link->irq.AssignedIRQ = 0;
}
i = pcmcia_request_configuration(link, &link->conf);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestConfiguration, i);
goto failed;
}
/* SPPP/Cisco HDLC device parts */
int netcount;
- int dosyncppp;
spinlock_t netlock;
#if SYNCLINK_GENERIC_HDLC
static int debug_level = 0;
static int maxframe[MAX_DEVICE_COUNT] = {0,};
-static int dosyncppp[MAX_DEVICE_COUNT] = {1,1,1,1};
module_param(break_on_load, bool, 0);
module_param(ttymajor, int, 0);
module_param(debug_level, int, 0);
module_param_array(maxframe, int, NULL, 0);
-module_param_array(dosyncppp, int, NULL, 0);
MODULE_LICENSE("GPL");
cfg = &(parse.cftable_entry);
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
- CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(&tuple, &parse));
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
if (cfg->index == 0)
if (info->line < MAX_DEVICE_COUNT) {
if (maxframe[info->line])
info->max_frame_size = maxframe[info->line];
- info->dosyncppp = dosyncppp[info->line];
}
mgslpc_device_count++;
#include <linux/timer.h>
#include <linux/ioport.h>
#include <linux/ide.h>
-#include <linux/hdreg.h>
#include <linux/major.h>
#include <linux/delay.h>
#include <asm/io.h>
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+ struct pcmcia_config_check {
+ unsigned long ctl_base;
+ int skip_vcc;
+ int is_kme;
+ };
+
+ static int pcmcia_check_one_config(struct pcmcia_device *pdev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+ {
+ struct pcmcia_config_check *stk = priv_data;
+
+ /* Check for matching Vcc, unless we're desperate */
+ if (!stk->skip_vcc) {
+ 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))
+ pdev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+ else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ pdev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+
+ if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
+ pdev->conf.ConfigIndex = cfg->index;
+ pdev->io.BasePort1 = io->win[0].base;
+ pdev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ pdev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ if (io->nwin == 2) {
+ pdev->io.NumPorts1 = 8;
+ pdev->io.BasePort2 = io->win[1].base;
+ pdev->io.NumPorts2 = (stk->is_kme) ? 2 : 1;
+ if (pcmcia_request_io(pdev, &pdev->io) != 0)
+ return -ENODEV;
+ stk->ctl_base = pdev->io.BasePort2;
+ } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
+ pdev->io.NumPorts1 = io->win[0].len;
+ pdev->io.NumPorts2 = 0;
+ if (pcmcia_request_io(pdev, &pdev->io) != 0)
+ return -ENODEV;
+ stk->ctl_base = pdev->io.BasePort1 + 0x0e;
+ } else
+ return -ENODEV;
+ /* If we've got this far, we're done */
+ return 0;
+ }
+ return -ENODEV;
+ }
+
static int ide_config(struct pcmcia_device *link)
{
ide_info_t *info = link->priv;
- tuple_t tuple;
- struct {
- u_short buf[128];
- cisparse_t parse;
- config_info_t conf;
- cistpl_cftable_entry_t dflt;
- } *stk = NULL;
- cistpl_cftable_entry_t *cfg;
- int pass, last_ret = 0, last_fn = 0, is_kme = 0;
+ struct pcmcia_config_check *stk = NULL;
+ int last_ret = 0, last_fn = 0, is_kme = 0;
unsigned long io_base, ctl_base;
struct ide_host *host;
DEBUG(0, "ide_config(0x%p)\n", link);
- stk = kzalloc(sizeof(*stk), GFP_KERNEL);
- if (!stk) goto err_mem;
- cfg = &stk->parse.cftable_entry;
-
- tuple.TupleData = (cisdata_t *)&stk->buf;
- tuple.TupleOffset = 0;
- tuple.TupleDataMax = 255;
- tuple.Attributes = 0;
-
is_kme = ((link->manf_id == MANFID_KME) &&
((link->card_id == PRODID_KME_KXLC005_A) ||
(link->card_id == PRODID_KME_KXLC005_B)));
- /* Not sure if this is right... look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
-
- pass = io_base = ctl_base = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- if (pcmcia_get_tuple_data(link, &tuple) != 0) goto next_entry;
- if (pcmcia_parse_tuple(link, &tuple, &stk->parse) != 0) goto next_entry;
-
- /* Check for matching Vcc, unless we're desperate */
- if (!pass) {
- if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (stk->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000)
- goto next_entry;
- } else if (stk->dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (stk->conf.Vcc != stk->dflt.vcc.param[CISTPL_POWER_VNOM] / 10000)
- goto next_entry;
- }
- }
-
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp =
- cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
- else if (stk->dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->conf.Vpp =
- stk->dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
-
- if ((cfg->io.nwin > 0) || (stk->dflt.io.nwin > 0)) {
- cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &stk->dflt.io;
- link->conf.ConfigIndex = cfg->index;
- link->io.BasePort1 = io->win[0].base;
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- if (!(io->flags & CISTPL_IO_16BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- if (io->nwin == 2) {
- link->io.NumPorts1 = 8;
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = (is_kme) ? 2 : 1;
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
- io_base = link->io.BasePort1;
- ctl_base = link->io.BasePort2;
- } else if ((io->nwin == 1) && (io->win[0].len >= 16)) {
- link->io.NumPorts1 = io->win[0].len;
- link->io.NumPorts2 = 0;
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
- io_base = link->io.BasePort1;
- ctl_base = link->io.BasePort1 + 0x0e;
- } else goto next_entry;
- /* If we've got this far, we're done */
- break;
- }
-
- next_entry:
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
- memcpy(&stk->dflt, cfg, sizeof(stk->dflt));
- if (pass) {
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
- } else if (pcmcia_get_next_tuple(link, &tuple) != 0) {
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- memset(&stk->dflt, 0, sizeof(stk->dflt));
- pass++;
- }
+ stk = kzalloc(sizeof(*stk), GFP_KERNEL);
+ if (!stk)
+ goto err_mem;
+ stk->is_kme = is_kme;
+ stk->skip_vcc = io_base = ctl_base = 0;
+
+ if (pcmcia_loop_config(link, pcmcia_check_one_config, stk)) {
+ stk->skip_vcc = 1;
+ if (pcmcia_loop_config(link, pcmcia_check_one_config, stk))
+ goto failed; /* No suitable config found */
}
+ io_base = link->io.BasePort1;
+ ctl_base = stk->ctl_base;
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
PCMCIA_DEVICE_MANF_CARD(0x000a, 0x0000), /* I-O Data CFA */
PCMCIA_DEVICE_MANF_CARD(0x001c, 0x0001), /* Mitsubishi CFA */
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
+ PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), /* SanDisk CFA */
PCMCIA_DEVICE_MANF_CARD(0x004f, 0x0000), /* Kingston */
+ PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), /* TI emulated */
PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */
if (link->io.NumPorts2 > 0) {
/* for master/slave multifunction cards */
link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
- link->irq.Attributes =
+ link->irq.Attributes =
IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
}
} else {
link->io.BasePort1 = j ^ 0x300;
link->io.BasePort2 = (j ^ 0x300) + 0x10;
ret = pcmcia_request_io(link, &link->io);
- if (ret == CS_SUCCESS) return ret;
+ if (ret == 0)
+ return ret;
}
return ret;
} else {
}
}
+ static int axnet_configcheck(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+ {
+ int i;
+ cistpl_io_t *io = &cfg->io;
+
+ if (cfg->index == 0 || cfg->io.nwin == 0)
+ return -ENODEV;
+
+ p_dev->conf.ConfigIndex = 0x05;
+ /* For multifunction cards, by convention, we configure the
+ network function with window 0, and serial with window 1 */
+ if (io->nwin > 1) {
+ i = (io->win[1].len > io->win[0].len);
+ p_dev->io.BasePort2 = io->win[1-i].base;
+ p_dev->io.NumPorts2 = io->win[1-i].len;
+ } else {
+ i = p_dev->io.NumPorts2 = 0;
+ }
+ p_dev->io.BasePort1 = io->win[i].base;
+ p_dev->io.NumPorts1 = io->win[i].len;
+ p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32)
+ return try_io_port(p_dev);
+
+ return -ENODEV;
+ }
+
static int axnet_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
axnet_dev_t *info = PRIV(dev);
- tuple_t tuple;
- cisparse_t parse;
int i, j, last_ret, last_fn;
- u_short buf[64];
DECLARE_MAC_BUF(mac);
DEBUG(0, "axnet_config(0x%p)\n", link);
- tuple.Attributes = 0;
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
-
/* don't trust the CIS on this; Linksys got it wrong */
link->conf.Present = 0x63;
-
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (last_ret == CS_SUCCESS) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- cistpl_io_t *io = &(parse.cftable_entry.io);
-
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
- cfg->index == 0 || cfg->io.nwin == 0)
- goto next_entry;
-
- link->conf.ConfigIndex = 0x05;
- /* For multifunction cards, by convention, we configure the
- network function with window 0, and serial with window 1 */
- if (io->nwin > 1) {
- i = (io->win[1].len > io->win[0].len);
- link->io.BasePort2 = io->win[1-i].base;
- link->io.NumPorts2 = io->win[1-i].len;
- } else {
- i = link->io.NumPorts2 = 0;
- }
- link->io.BasePort1 = io->win[i].base;
- link->io.NumPorts1 = io->win[i].len;
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) {
- last_ret = try_io_port(link);
- if (last_ret == CS_SUCCESS) break;
- }
- next_entry:
- last_ret = pcmcia_get_next_tuple(link, &tuple);
- }
- if (last_ret != CS_SUCCESS) {
+ last_ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
+ if (last_ret != 0) {
cs_error(link, RequestIO, last_ret);
goto failed;
}
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXD", 0x5261440f, 0x436768c5),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEtherII PCC-TXD", 0x5261440f, 0x730df72e),
PCMCIA_DEVICE_PROD_ID12("Dynalink", "L100C16", 0x55632fd5, 0x66bc2a90),
+ PCMCIA_DEVICE_PROD_ID12("IO DATA", "ETXPCM", 0x547e66dc, 0x233adac2),
PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8),
PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC3-TX", 0x481e0094, 0xf91af609),
PCMCIA_DEVICE_PROD_ID12("PCMCIA", "100BASE", 0x281f1c5d, 0x7c2add04),
req.Base = 0; req.Size = 0;
req.AccessSpeed = 0;
i = pcmcia_request_window(&link, &req, &link->win);
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestWindow, i);
return NULL;
}
iounmap(virt);
j = pcmcia_release_window(link->win);
- if (j != CS_SUCCESS)
+ if (j != 0)
cs_error(link, ReleaseWindow, j);
return (i < NR_INFO) ? hw_info+i : NULL;
} /* get_hwinfo */
link->io.BasePort1 = j ^ 0x300;
link->io.BasePort2 = (j ^ 0x300) + 0x10;
ret = pcmcia_request_io(link, &link->io);
- if (ret == CS_SUCCESS) return ret;
+ if (ret == 0)
+ return ret;
}
return ret;
} else {
}
}
+ static int pcnet_confcheck(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+ {
+ int *has_shmem = priv_data;
+ int i;
+ cistpl_io_t *io = &cfg->io;
+
+ if (cfg->index == 0 || cfg->io.nwin == 0)
+ return -EINVAL;
+
+ /* For multifunction cards, by convention, we configure the
+ network function with window 0, and serial with window 1 */
+ if (io->nwin > 1) {
+ i = (io->win[1].len > io->win[0].len);
+ p_dev->io.BasePort2 = io->win[1-i].base;
+ p_dev->io.NumPorts2 = io->win[1-i].len;
+ } else {
+ i = p_dev->io.NumPorts2 = 0;
+ }
+
+ *has_shmem = ((cfg->mem.nwin == 1) &&
+ (cfg->mem.win[0].len >= 0x4000));
+ p_dev->io.BasePort1 = io->win[i].base;
+ p_dev->io.NumPorts1 = io->win[i].len;
+ p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32)
+ return try_io_port(p_dev);
+
+ return 0;
+ }
+
static int pcnet_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
pcnet_dev_t *info = PRIV(dev);
- tuple_t tuple;
- cisparse_t parse;
- int i, last_ret, last_fn, start_pg, stop_pg, cm_offset;
+ int last_ret, last_fn, start_pg, stop_pg, cm_offset;
int has_shmem = 0;
- u_short buf[64];
hw_info_t *local_hw_info;
DECLARE_MAC_BUF(mac);
DEBUG(0, "pcnet_config(0x%p)\n", link);
- tuple.TupleData = (cisdata_t *)buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (last_ret == CS_SUCCESS) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- cistpl_io_t *io = &(parse.cftable_entry.io);
-
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0 ||
- cfg->index == 0 || cfg->io.nwin == 0)
- goto next_entry;
-
- link->conf.ConfigIndex = cfg->index;
- /* For multifunction cards, by convention, we configure the
- network function with window 0, and serial with window 1 */
- if (io->nwin > 1) {
- i = (io->win[1].len > io->win[0].len);
- link->io.BasePort2 = io->win[1-i].base;
- link->io.NumPorts2 = io->win[1-i].len;
- } else {
- i = link->io.NumPorts2 = 0;
- }
- has_shmem = ((cfg->mem.nwin == 1) &&
- (cfg->mem.win[0].len >= 0x4000));
- link->io.BasePort1 = io->win[i].base;
- link->io.NumPorts1 = io->win[i].len;
- link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
- if (link->io.NumPorts1 + link->io.NumPorts2 >= 32) {
- last_ret = try_io_port(link);
- if (last_ret == CS_SUCCESS) break;
- }
- next_entry:
- last_ret = pcmcia_get_next_tuple(link, &tuple);
- }
- if (last_ret != CS_SUCCESS) {
+ last_ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem);
+ if (last_ret) {
cs_error(link, RequestIO, last_ret);
goto failed;
}
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d),
PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa),
+ PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-TD", 0x5261440f, 0x47d5ca83),
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9),
PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2),
PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2),
PCMCIA_DEVICE_PROD_ID1("CyQ've 10 Base-T LAN CARD", 0x94faf360),
PCMCIA_DEVICE_PROD_ID1("EP-210 PCMCIA LAN CARD.", 0x8850b4de),
PCMCIA_DEVICE_PROD_ID1("ETHER-C16", 0x06a8514f),
- PCMCIA_DEVICE_PROD_ID1("IC-CARD", 0x60cb09a6),
PCMCIA_DEVICE_PROD_ID1("NE2000 Compatible", 0x75b8ad5a),
PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078),
/* too generic! */
* Some more prototypes
*/
static int do_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void do_tx_timeout(struct net_device *dev);
+static void xirc_tx_timeout(struct net_device *dev);
static void xirc2ps_tx_timeout_task(struct work_struct *work);
static struct net_device_stats *do_get_stats(struct net_device *dev);
static void set_addresses(struct net_device *dev);
if ((err = pcmcia_get_first_tuple(handle, tuple)) == 0 &&
(err = pcmcia_get_tuple_data(handle, tuple)) == 0)
- err = pcmcia_parse_tuple(handle, tuple, parse);
+ err = pcmcia_parse_tuple(tuple, parse);
return err;
}
if ((err = pcmcia_get_next_tuple(handle, tuple)) == 0 &&
(err = pcmcia_get_tuple_data(handle, tuple)) == 0)
- err = pcmcia_parse_tuple(handle, tuple, parse);
+ err = pcmcia_parse_tuple(tuple, parse);
return err;
}
dev->open = &do_open;
dev->stop = &do_stop;
#ifdef HAVE_TX_TIMEOUT
- dev->tx_timeout = do_tx_timeout;
+ dev->tx_timeout = xirc_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task);
#endif
return 0;
}
+ static int
+ xirc2ps_config_modem(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+ {
+ unsigned int ioaddr;
+
+ if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
+ for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
+ p_dev->io.BasePort2 = cf->io.win[0].base;
+ p_dev->io.BasePort1 = ioaddr;
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ }
+ return -ENODEV;
+ }
+
+ static int
+ xirc2ps_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cf,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+ {
+ int *pass = priv_data;
+
+ if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
+ p_dev->io.BasePort2 = cf->io.win[0].base;
+ p_dev->io.BasePort1 = p_dev->io.BasePort2
+ + (*pass ? (cf->index & 0x20 ? -24:8)
+ : (cf->index & 0x20 ? 8:-24));
+ if (!pcmcia_request_io(p_dev, &p_dev->io))
+ return 0;
+ }
+ return -ENODEV;
+
+ }
+
/****************
* xirc2ps_config() is scheduled to run after a CARD_INSERTION event
* is received, to configure the PCMCIA socket, and to make the
{
struct net_device *dev = link->priv;
local_info_t *local = netdev_priv(dev);
+ unsigned int ioaddr;
tuple_t tuple;
cisparse_t parse;
- unsigned int ioaddr;
int err, i;
u_char buf[64];
cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data;
- cistpl_cftable_entry_t *cf = &parse.cftable_entry;
DECLARE_MAC_BUF(mac);
local->dingo_ccr = NULL;
/* Take the Modem IO port from the CIS and scan for a free
* Ethernet port */
link->io.NumPorts1 = 16; /* no Mako stuff anymore */
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (err = first_tuple(link, &tuple, &parse); !err;
- err = next_tuple(link, &tuple, &parse)) {
- if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) {
- for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) {
- link->conf.ConfigIndex = cf->index ;
- link->io.BasePort2 = cf->io.win[0].base;
- link->io.BasePort1 = ioaddr;
- if (!(err=pcmcia_request_io(link, &link->io)))
- goto port_found;
- }
- }
- }
+ if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL))
+ goto port_found;
} else {
link->io.NumPorts1 = 18;
/* We do 2 passes here: The first one uses the regular mapping and
* mirrored every 32 bytes. Actually we use a mirrored port for
* the Mako if (on the first pass) the COR bit 5 is set.
*/
- for (pass=0; pass < 2; pass++) {
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- for (err = first_tuple(link, &tuple, &parse); !err;
- err = next_tuple(link, &tuple, &parse)){
- if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8){
- link->conf.ConfigIndex = cf->index ;
- link->io.BasePort2 = cf->io.win[0].base;
- link->io.BasePort1 = link->io.BasePort2
- + (pass ? (cf->index & 0x20 ? -24:8)
- : (cf->index & 0x20 ? 8:-24));
- if (!(err=pcmcia_request_io(link, &link->io)))
+ for (pass=0; pass < 2; pass++)
+ if (!pcmcia_loop_config(link, xirc2ps_config_check, &pass))
goto port_found;
- }
- }
- }
/* if special option:
* try to configure as Ethernet only.
* .... */
}
static void
-do_tx_timeout(struct net_device *dev)
+xirc_tx_timeout(struct net_device *dev)
{
local_info_t *lp = netdev_priv(dev);
lp->stats.tx_errors++;
DEBUG(0, "airo_attach()\n");
/* Interrupt setup */
- p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = NULL;
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+ static int airo_cs_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+ {
+ win_req_t *req = priv_data;
+
+ if (cfg->index == 0)
+ return -ENODEV;
+
+ /* 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->vpp1.present & (1<<CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp = cfg->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)
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
+ /* IO window settings */
+ 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))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.BasePort1 = io->win[0].base;
+ p_dev->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ 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(p_dev, &p_dev->io) != 0)
+ return -ENODEV;
+
+ /*
+ Now set up a common memory window, if needed. There is room
+ in the struct pcmcia_device structure for one memory window handle,
+ but if the base addresses need to be saved, or if multiple
+ windows are needed, the info should go in the private data
+ structure for this device.
+
+ Note that the memory window base is a physical address, and
+ needs to be mapped to virtual space with ioremap() before it
+ is used.
+ */
+ if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) {
+ cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem;
+ memreq_t map;
+ req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
+ req->Base = mem->win[0].host_addr;
+ req->Size = mem->win[0].len;
+ req->AccessSpeed = 0;
+ if (pcmcia_request_window(&p_dev, req, &p_dev->win) != 0)
+ return -ENODEV;
+ map.Page = 0;
+ map.CardOffset = mem->win[0].card_addr;
+ if (pcmcia_map_mem_page(p_dev->win, &map) != 0)
+ return -ENODEV;
+ }
+ /* If we got this far, we're cool! */
+ return 0;
+ }
+
+
static int airo_config(struct pcmcia_device *link)
{
- tuple_t tuple;
- cisparse_t parse;
local_info_t *dev;
+ win_req_t *req;
int last_fn, last_ret;
- u_char buf[64];
- win_req_t req;
- memreq_t map;
dev = link->priv;
DEBUG(0, "airo_config(0x%p)\n", link);
+ req = kzalloc(sizeof(win_req_t), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ /*
+ * In this loop, we scan the CIS for configuration table
+ * entries, each of which describes a valid card
+ * configuration, including voltage, IO window, memory window,
+ * and interrupt settings.
+ *
+ * We make no assumptions about the card to be configured: we
+ * use just the information available in the CIS. In an ideal
+ * world, this would work for any PCMCIA card, but it requires
+ * a complete and accurate CIS. In practice, a driver usually
+ * "knows" most of these things without consulting the CIS,
+ * and most client drivers will only use the CIS to fill in
+ * implementation-defined details.
+ */
+ last_ret = pcmcia_loop_config(link, airo_cs_config_check, req);
+ if (last_ret)
+ goto failed;
+
/*
- In this loop, we scan the CIS for configuration table entries,
- each of which describes a valid card configuration, including
- voltage, IO window, memory window, and interrupt settings.
-
- We make no assumptions about the card to be configured: we use
- just the information available in the CIS. In an ideal world,
- this would work for any PCMCIA card, but it requires a complete
- and accurate CIS. In practice, a driver usually "knows" most of
- these things without consulting the CIS, and most client drivers
- will only use the CIS to fill in implementation-defined details.
+ Allocate an interrupt line. Note that this does not assign a
+ handler to the interrupt, unless the 'Handler' member of the
+ irq structure is initialized.
*/
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- cistpl_cftable_entry_t dflt = { 0 };
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &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;
- }
-
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->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;
-
- /* Do we need to allocate an interrupt? */
- if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
- link->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;
- if (!(io->flags & CISTPL_IO_8BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
- if (!(io->flags & CISTPL_IO_16BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.BasePort1 = io->win[0].base;
- link->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;
- }
- }
-
- /* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
-
- /*
- Now set up a common memory window, if needed. There is room
- in the struct pcmcia_device structure for one memory window handle,
- but if the base addresses need to be saved, or if multiple
- windows are needed, the info should go in the private data
- structure for this device.
-
- Note that the memory window base is a physical address, and
- needs to be mapped to virtual space with ioremap() before it
- is used.
- */
- 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.Base = mem->win[0].host_addr;
- req.Size = mem->win[0].len;
- req.AccessSpeed = 0;
- if (pcmcia_request_window(&link, &req, &link->win) != 0)
- goto next_entry;
- map.Page = 0; map.CardOffset = mem->win[0].card_addr;
- if (pcmcia_map_mem_page(link->win, &map) != 0)
- goto next_entry;
- }
- /* If we got this far, we're cool! */
- break;
-
- next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
- }
-
- /*
- Allocate an interrupt line. Note that this does not assign a
- handler to the interrupt, unless the 'Handler' member of the
- irq structure is initialized.
- */
if (link->conf.Attributes & CONF_ENABLE_IRQ)
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
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", req->Base,
+ req->Base+req->Size-1);
printk("\n");
+ kfree(req);
return 0;
cs_failed:
cs_error(link, last_fn, last_ret);
+ failed:
airo_release(link);
+ kfree(req);
return -ENODEV;
} /* airo_config */
DEBUG(0, "atmel_attach()\n");
/* Interrupt setup */
- p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = NULL;
return 0;
}
+ static int atmel_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+ {
+ if (cfg->index == 0)
+ return -ENODEV;
+
+ /* 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->vpp1.present & (1<<CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp = cfg->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)
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
+ /* IO window settings */
+ 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))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ p_dev->io.BasePort1 = io->win[0].base;
+ p_dev->io.NumPorts1 = io->win[0].len;
+ if (io->nwin > 1) {
+ 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 */
+ return pcmcia_request_io(p_dev, &p_dev->io);
+ }
+
static int atmel_config(struct pcmcia_device *link)
{
- tuple_t tuple;
- cisparse_t parse;
local_info_t *dev;
int last_fn, last_ret;
- u_char buf[64];
struct pcmcia_device_id *did;
dev = link->priv;
DEBUG(0, "atmel_config(0x%p)\n", link);
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
-
/*
In this loop, we scan the CIS for configuration table entries,
each of which describes a valid card configuration, including
these things without consulting the CIS, and most client drivers
will only use the CIS to fill in implementation-defined details.
*/
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- cistpl_cftable_entry_t dflt = { 0 };
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &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;
- }
-
- /* Use power settings for Vcc and Vpp if present */
- /* Note that the CIS values need to be rescaled */
- if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
- link->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;
-
- /* Do we need to allocate an interrupt? */
- if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
- link->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;
- if (!(io->flags & CISTPL_IO_8BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
- if (!(io->flags & CISTPL_IO_16BIT))
- link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
- link->io.BasePort1 = io->win[0].base;
- link->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;
- }
- }
-
- /* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
-
- /* If we got this far, we're cool! */
- break;
-
- next_entry:
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
- }
+ if (pcmcia_loop_config(link, atmel_config_check, NULL))
+ goto failed;
/*
Allocate an interrupt line. Note that this does not assign a
cs_failed:
cs_error(link, last_fn, last_ret);
+ failed:
atmel_release(link);
return -ENODEV;
}
if (ret < 0) {
lbs_pr_err("can't download helper at 0x%x, ret %d\n",
sent, ret);
- goto done;
+ goto err_release;
}
if (count == 0)
sent += count;
}
+err_release:
release_firmware(fw);
- ret = 0;
-
done:
lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
return ret;
}
ret = if_cs_poll_while_fw_download(card, IF_CS_SCRATCH, 0x5a);
- if (ret < 0) {
+ if (ret < 0)
lbs_pr_err("firmware download failed\n");
- goto err_release;
- }
-
- ret = 0;
- goto done;
-
err_release:
release_firmware(fw);
ret = if_cs_send_cmd(priv, buf, nb);
break;
default:
- lbs_pr_err("%s: unsupported type %d\n", __FUNCTION__, type);
+ lbs_pr_err("%s: unsupported type %d\n", __func__, type);
}
lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
if ((ret = pcmcia_get_first_tuple(p_dev, &tuple)) != 0 ||
(ret = pcmcia_get_tuple_data(p_dev, &tuple)) != 0 ||
- (ret = pcmcia_parse_tuple(p_dev, &tuple, &parse)) != 0)
+ (ret = pcmcia_parse_tuple(&tuple, &parse)) != 0)
{
lbs_pr_err("error in pcmcia_get_first_tuple etc\n");
goto out1;
link->io.IOAddrLines = 5;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = &netwave_interrupt;
for (i = j = 0x0; j < 0x400; j += 0x20) {
link->io.BasePort1 = j ^ 0x300;
i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS) break;
+ if (i == 0)
+ break;
}
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIO, i);
goto failed;
}
/* We need atomic ops here, because we're not holding the lock */
set_bit(0, &card->hard_reset_in_progress);
- err = pcmcia_reset_card(link, NULL);
+ err = pcmcia_reset_card(link->socket);
if (err)
return err;
struct orinoco_private *priv;
struct orinoco_pccard *card;
- dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset);
+ dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
+ orinoco_cs_hard_reset, NULL);
if (! dev)
return -ENOMEM;
priv = netdev_priv(dev);
link->priv = dev;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = orinoco_interrupt;
link->irq.Instance = dev;
last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
} while (0)
+ static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+ {
+ if (cfg->index == 0)
+ 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) {
+ DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ if (!ignore_cis_vcc)
+ goto next_entry;
+ }
+ } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+ DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ if (!ignore_cis_vcc)
+ goto next_entry;
+ }
+ }
+
+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp =
+ cfg->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? */
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
+ /* IO window settings */
+ 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))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ 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) {
+ 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(p_dev, &p_dev->io) != 0)
+ goto next_entry;
+ }
+ return 0;
+
+ next_entry:
+ pcmcia_disable_device(p_dev);
+ return -ENODEV;
+ };
+
static int
orinoco_cs_config(struct pcmcia_device *link)
{
struct orinoco_pccard *card = priv->card;
hermes_t *hw = &priv->hw;
int last_fn, last_ret;
- u_char buf[64];
- config_info_t conf;
- tuple_t tuple;
- cisparse_t parse;
void __iomem *mem;
- /* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(link, &conf));
-
/*
* In this loop, we scan the CIS for configuration table
* entries, each of which describes a valid card
* and most client drivers will only use the CIS to fill in
* implementation-defined details.
*/
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- cistpl_cftable_entry_t dflt = { .index = 0 };
-
- if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
- || (pcmcia_parse_tuple(link, &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;
-
- /* 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) {
- DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, cfg CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
- if (!ignore_cis_vcc)
- goto next_entry;
- }
- } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, dflt CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
- if(!ignore_cis_vcc)
- goto next_entry;
- }
- }
-
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->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;
-
- /* Do we need to allocate an interrupt? */
- link->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;
- if (!(io->flags & CISTPL_IO_8BIT))
- link->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;
- if (io->nwin > 1) {
- link->io.Attributes2 =
- link->io.Attributes1;
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = io->win[1].len;
- }
-
- /* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
- }
-
-
- /* If we got this far, we're cool! */
-
- break;
-
- next_entry:
- pcmcia_disable_device(link);
- last_ret = pcmcia_get_next_tuple(link, &tuple);
- if (last_ret == CS_NO_MORE_ITEMS) {
+ last_ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL);
+ if (last_ret) {
+ if (!ignore_cis_vcc)
printk(KERN_ERR PFX "GetNextTuple(): No matching "
"CIS configuration. Maybe you need the "
"ignore_cis_vcc=1 parameter.\n");
- goto cs_failed;
- }
+ cs_error(link, RequestIO, last_ret);
+ goto failed;
}
/*
"0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
link->irq.AssignedIRQ, link->io.BasePort1,
link->io.BasePort1 + link->io.NumPorts1 - 1);
-
return 0;
cs_failed:
p_dev->io.IOAddrLines = 5;
/* Interrupt setup. For PCMCIA, driver takes what's given */
- p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = &ray_interrupt;
iounmap(local->amem);
/* Do bother checking to see if these succeed or not */
i = pcmcia_release_window(local->amem_handle);
- if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i);
+ if ( i != 0 ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i);
i = pcmcia_release_window(local->rmem_handle);
- if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i);
+ if ( i != 0 ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i);
pcmcia_disable_device(link);
DEBUG(2,"ray_release ending\n");
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/firmware.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include "orinoco.h"
-static const char primary_fw_name[] = "symbol_sp24t_prim_fw";
-static const char secondary_fw_name[] = "symbol_sp24t_sec_fw";
-
/********************************************************************/
/* Module stuff */
/********************************************************************/
static int spectrum_cs_config(struct pcmcia_device *link);
static void spectrum_cs_release(struct pcmcia_device *link);
-/********************************************************************/
-/* Firmware downloader */
-/********************************************************************/
-
-/* Position of PDA in the adapter memory */
-#define EEPROM_ADDR 0x3000
-#define EEPROM_LEN 0x200
-#define PDA_OFFSET 0x100
-
-#define PDA_ADDR (EEPROM_ADDR + PDA_OFFSET)
-#define PDA_WORDS ((EEPROM_LEN - PDA_OFFSET) / 2)
-
/* Constants for the CISREG_CCSR register */
#define HCR_RUN 0x07 /* run firmware after reset */
#define HCR_IDLE 0x0E /* don't run firmware after reset */
#define HCR_MEM16 0x10 /* memory width bit, should be preserved */
-/*
- * AUX port access. To unlock the AUX port write the access keys to the
- * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
- * register. Then read it and make sure it's HERMES_AUX_ENABLED.
- */
-#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
-#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
-#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
-
-#define HERMES_AUX_PW0 0xFE01
-#define HERMES_AUX_PW1 0xDC23
-#define HERMES_AUX_PW2 0xBA45
-
-/* End markers */
-#define PDI_END 0x00000000 /* End of PDA */
-#define BLOCK_END 0xFFFFFFFF /* Last image block */
-#define TEXT_END 0x1A /* End of text header */
-
-/*
- * The following structures have little-endian fields denoted by
- * the leading underscore. Don't access them directly - use inline
- * functions defined below.
- */
-
-/*
- * The binary image to be downloaded consists of series of data blocks.
- * Each block has the following structure.
- */
-struct dblock {
- __le32 addr; /* adapter address where to write the block */
- __le16 len; /* length of the data only, in bytes */
- char data[0]; /* data to be written */
-} __attribute__ ((packed));
-
-/*
- * Plug Data References are located in in the image after the last data
- * block. They refer to areas in the adapter memory where the plug data
- * items with matching ID should be written.
- */
-struct pdr {
- __le32 id; /* record ID */
- __le32 addr; /* adapter address where to write the data */
- __le32 len; /* expected length of the data, in bytes */
- char next[0]; /* next PDR starts here */
-} __attribute__ ((packed));
-
-
-/*
- * Plug Data Items are located in the EEPROM read from the adapter by
- * primary firmware. They refer to the device-specific data that should
- * be plugged into the secondary firmware.
- */
-struct pdi {
- __le16 len; /* length of ID and data, in words */
- __le16 id; /* record ID */
- char data[0]; /* plug data */
-} __attribute__ ((packed));
-
-
-/* Functions for access to little-endian data */
-static inline u32
-dblock_addr(const struct dblock *blk)
-{
- return le32_to_cpu(blk->addr);
-}
-
-static inline u32
-dblock_len(const struct dblock *blk)
-{
- return le16_to_cpu(blk->len);
-}
-
-static inline u32
-pdr_id(const struct pdr *pdr)
-{
- return le32_to_cpu(pdr->id);
-}
-
-static inline u32
-pdr_addr(const struct pdr *pdr)
-{
- return le32_to_cpu(pdr->addr);
-}
-
-static inline u32
-pdr_len(const struct pdr *pdr)
-{
- return le32_to_cpu(pdr->len);
-}
-
-static inline u32
-pdi_id(const struct pdi *pdi)
-{
- return le16_to_cpu(pdi->id);
-}
-
-/* Return length of the data only, in bytes */
-static inline u32
-pdi_len(const struct pdi *pdi)
-{
- return 2 * (le16_to_cpu(pdi->len) - 1);
-}
-
-
-/* Set address of the auxiliary port */
-static inline void
-spectrum_aux_setaddr(hermes_t *hw, u32 addr)
-{
- hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
- hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
-}
-
-
-/* Open access to the auxiliary port */
-static int
-spectrum_aux_open(hermes_t *hw)
-{
- int i;
-
- /* Already open? */
- if (hermes_read_reg(hw, HERMES_CONTROL) == HERMES_AUX_ENABLED)
- return 0;
-
- hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
- hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
- hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
- hermes_write_reg(hw, HERMES_CONTROL, HERMES_AUX_ENABLE);
-
- for (i = 0; i < 20; i++) {
- udelay(10);
- if (hermes_read_reg(hw, HERMES_CONTROL) ==
- HERMES_AUX_ENABLED)
- return 0;
- }
-
- return -EBUSY;
-}
-
#define CS_CHECK(fn, ret) \
do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
return -ENODEV;
}
+/********************************************************************/
+/* Device methods */
+/********************************************************************/
-/*
- * Scan PDR for the record with the specified RECORD_ID.
- * If it's not found, return NULL.
- */
-static struct pdr *
-spectrum_find_pdr(struct pdr *first_pdr, u32 record_id)
-{
- struct pdr *pdr = first_pdr;
-
- while (pdr_id(pdr) != PDI_END) {
- /*
- * PDR area is currently not terminated by PDI_END.
- * It's followed by CRC records, which have the type
- * field where PDR has length. The type can be 0 or 1.
- */
- if (pdr_len(pdr) < 2)
- return NULL;
-
- /* If the record ID matches, we are done */
- if (pdr_id(pdr) == record_id)
- return pdr;
-
- pdr = (struct pdr *) pdr->next;
- }
- return NULL;
-}
-
-
-/* Process one Plug Data Item - find corresponding PDR and plug it */
-static int
-spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi)
-{
- struct pdr *pdr;
-
- /* Find the PDI corresponding to this PDR */
- pdr = spectrum_find_pdr(first_pdr, pdi_id(pdi));
-
- /* No match is found, safe to ignore */
- if (!pdr)
- return 0;
-
- /* Lengths of the data in PDI and PDR must match */
- if (pdi_len(pdi) != pdr_len(pdr))
- return -EINVAL;
-
- /* do the actual plugging */
- spectrum_aux_setaddr(hw, pdr_addr(pdr));
- hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi));
-
- return 0;
-}
-
-
-/* Read PDA from the adapter */
-static int
-spectrum_read_pda(hermes_t *hw, __le16 *pda, int pda_len)
-{
- int ret;
- int pda_size;
-
- /* Issue command to read EEPROM */
- ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
- if (ret)
- return ret;
-
- /* Open auxiliary port */
- ret = spectrum_aux_open(hw);
- if (ret)
- return ret;
-
- /* read PDA from EEPROM */
- spectrum_aux_setaddr(hw, PDA_ADDR);
- hermes_read_words(hw, HERMES_AUXDATA, pda, pda_len / 2);
-
- /* Check PDA length */
- pda_size = le16_to_cpu(pda[0]);
- if (pda_size > pda_len)
- return -EINVAL;
-
- return 0;
-}
-
-
-/* Parse PDA and write the records into the adapter */
-static int
-spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block,
- __le16 *pda)
-{
- int ret;
- struct pdi *pdi;
- struct pdr *first_pdr;
- const struct dblock *blk = first_block;
-
- /* Skip all blocks to locate Plug Data References */
- while (dblock_addr(blk) != BLOCK_END)
- blk = (struct dblock *) &blk->data[dblock_len(blk)];
-
- first_pdr = (struct pdr *) blk;
-
- /* Go through every PDI and plug them into the adapter */
- pdi = (struct pdi *) (pda + 2);
- while (pdi_id(pdi) != PDI_END) {
- ret = spectrum_plug_pdi(hw, first_pdr, pdi);
- if (ret)
- return ret;
-
- /* Increment to the next PDI */
- pdi = (struct pdi *) &pdi->data[pdi_len(pdi)];
- }
- return 0;
-}
-
-
-/* Load firmware blocks into the adapter */
-static int
-spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block)
-{
- const struct dblock *blk;
- u32 blkaddr;
- u32 blklen;
-
- blk = first_block;
- blkaddr = dblock_addr(blk);
- blklen = dblock_len(blk);
-
- while (dblock_addr(blk) != BLOCK_END) {
- spectrum_aux_setaddr(hw, blkaddr);
- hermes_write_bytes(hw, HERMES_AUXDATA, blk->data,
- blklen);
-
- blk = (struct dblock *) &blk->data[blklen];
- blkaddr = dblock_addr(blk);
- blklen = dblock_len(blk);
- }
- return 0;
-}
-
-
-/*
- * Process a firmware image - stop the card, load the firmware, reset
- * the card and make sure it responds. For the secondary firmware take
- * care of the PDA - read it and then write it on top of the firmware.
- */
static int
-spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link,
- const unsigned char *image, int secondary)
+spectrum_cs_hard_reset(struct orinoco_private *priv)
{
- int ret;
- const unsigned char *ptr;
- const struct dblock *first_block;
-
- /* Plug Data Area (PDA) */
- __le16 pda[PDA_WORDS];
-
- /* Binary block begins after the 0x1A marker */
- ptr = image;
- while (*ptr++ != TEXT_END);
- first_block = (const struct dblock *) ptr;
-
- /* Read the PDA */
- if (secondary) {
- ret = spectrum_read_pda(hw, pda, sizeof(pda));
- if (ret)
- return ret;
- }
-
- /* Stop the firmware, so that it can be safely rewritten */
- ret = spectrum_reset(link, 1);
- if (ret)
- return ret;
-
- /* Program the adapter with new firmware */
- ret = spectrum_load_blocks(hw, first_block);
- if (ret)
- return ret;
-
- /* Write the PDA to the adapter */
- if (secondary) {
- ret = spectrum_apply_pda(hw, first_block, pda);
- if (ret)
- return ret;
- }
-
- /* Run the firmware */
- ret = spectrum_reset(link, 0);
- if (ret)
- return ret;
-
- /* Reset hermes chip and make sure it responds */
- ret = hermes_init(hw);
-
- /* hermes_reset() should return 0 with the secondary firmware */
- if (secondary && ret != 0)
- return -ENODEV;
+ struct orinoco_pccard *card = priv->card;
+ struct pcmcia_device *link = card->p_dev;
- /* And this should work with any firmware */
- if (!hermes_present(hw))
- return -ENODEV;
+ /* Soft reset using COR and HCR */
+ spectrum_reset(link, 0);
return 0;
}
-
-/*
- * Download the firmware into the card, this also does a PCMCIA soft
- * reset on the card, to make sure it's in a sane state.
- */
static int
-spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link)
-{
- int ret;
- const struct firmware *fw_entry;
-
- if (request_firmware(&fw_entry, primary_fw_name,
- &handle_to_dev(link)) != 0) {
- printk(KERN_ERR PFX "Cannot find firmware: %s\n",
- primary_fw_name);
- return -ENOENT;
- }
-
- /* Load primary firmware */
- ret = spectrum_dl_image(hw, link, fw_entry->data, 0);
- release_firmware(fw_entry);
- if (ret) {
- printk(KERN_ERR PFX "Primary firmware download failed\n");
- return ret;
- }
-
- if (request_firmware(&fw_entry, secondary_fw_name,
- &handle_to_dev(link)) != 0) {
- printk(KERN_ERR PFX "Cannot find firmware: %s\n",
- secondary_fw_name);
- return -ENOENT;
- }
-
- /* Load secondary firmware */
- ret = spectrum_dl_image(hw, link, fw_entry->data, 1);
- release_firmware(fw_entry);
- if (ret) {
- printk(KERN_ERR PFX "Secondary firmware download failed\n");
- }
-
- return ret;
-}
-
-/********************************************************************/
-/* Device methods */
-/********************************************************************/
-
-static int
-spectrum_cs_hard_reset(struct orinoco_private *priv)
+spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle)
{
struct orinoco_pccard *card = priv->card;
struct pcmcia_device *link = card->p_dev;
- int err;
- if (!hermes_present(&priv->hw)) {
- /* The firmware needs to be reloaded */
- if (spectrum_dl_firmware(&priv->hw, link) != 0) {
- printk(KERN_ERR PFX "Firmware download failed\n");
- err = -ENODEV;
- }
- } else {
- /* Soft reset using COR and HCR */
- spectrum_reset(link, 0);
- }
-
- return 0;
+ return spectrum_reset(link, idle);
}
/********************************************************************/
struct orinoco_private *priv;
struct orinoco_pccard *card;
- dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);
+ dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
+ spectrum_cs_hard_reset,
+ spectrum_cs_stop_firmware);
if (! dev)
return -ENOMEM;
priv = netdev_priv(dev);
link->priv = dev;
/* Interrupt setup */
- link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = orinoco_interrupt;
link->irq.Instance = dev;
* device available to the system.
*/
+ static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
+ cistpl_cftable_entry_t *cfg,
+ cistpl_cftable_entry_t *dflt,
+ unsigned int vcc,
+ void *priv_data)
+ {
+ if (cfg->index == 0)
+ 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) {
+ DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ if (!ignore_cis_vcc)
+ goto next_entry;
+ }
+ } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+ if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+ DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ if (!ignore_cis_vcc)
+ goto next_entry;
+ }
+ }
+
+ if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
+ p_dev->conf.Vpp =
+ cfg->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? */
+ p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
+
+ /* IO window settings */
+ 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))
+ p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
+ if (!(io->flags & CISTPL_IO_16BIT))
+ 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) {
+ 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(p_dev, &p_dev->io) != 0)
+ goto next_entry;
+ }
+ return 0;
+
+ next_entry:
+ pcmcia_disable_device(p_dev);
+ return -ENODEV;
+ };
+
static int
spectrum_cs_config(struct pcmcia_device *link)
{
struct orinoco_pccard *card = priv->card;
hermes_t *hw = &priv->hw;
int last_fn, last_ret;
- u_char buf[64];
- config_info_t conf;
- tuple_t tuple;
- cisparse_t parse;
void __iomem *mem;
- /* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo,
- pcmcia_get_configuration_info(link, &conf));
-
/*
* In this loop, we scan the CIS for configuration table
* entries, each of which describes a valid card
* and most client drivers will only use the CIS to fill in
* implementation-defined details.
*/
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- tuple.Attributes = 0;
- tuple.TupleData = buf;
- tuple.TupleDataMax = sizeof(buf);
- tuple.TupleOffset = 0;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
- cistpl_cftable_entry_t dflt = { .index = 0 };
-
- if ( (pcmcia_get_tuple_data(link, &tuple) != 0)
- || (pcmcia_parse_tuple(link, &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;
-
- /* 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) {
- DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
- if (!ignore_cis_vcc)
- goto next_entry;
- }
- } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
- if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
- if(!ignore_cis_vcc)
- goto next_entry;
- }
- }
-
- if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
- link->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;
-
- /* Do we need to allocate an interrupt? */
- link->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;
- if (!(io->flags & CISTPL_IO_8BIT))
- link->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;
- if (io->nwin > 1) {
- link->io.Attributes2 =
- link->io.Attributes1;
- link->io.BasePort2 = io->win[1].base;
- link->io.NumPorts2 = io->win[1].len;
- }
-
- /* This reserves IO space but doesn't actually enable it */
- if (pcmcia_request_io(link, &link->io) != 0)
- goto next_entry;
- }
-
-
- /* If we got this far, we're cool! */
-
- break;
-
- next_entry:
- pcmcia_disable_device(link);
- last_ret = pcmcia_get_next_tuple(link, &tuple);
- if (last_ret == CS_NO_MORE_ITEMS) {
+ last_ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL);
+ if (last_ret) {
+ if (!ignore_cis_vcc)
printk(KERN_ERR PFX "GetNextTuple(): No matching "
"CIS configuration. Maybe you need the "
"ignore_cis_vcc=1 parameter.\n");
- goto cs_failed;
- }
+ cs_error(link, RequestIO, last_ret);
+ goto failed;
}
/*
dev->irq = link->irq.AssignedIRQ;
card->node.major = card->node.minor = 0;
- /* Reset card and download firmware */
+ /* Reset card */
if (spectrum_cs_hard_reset(priv) != 0) {
goto failed;
}
lp->mc_count = 0;
wv_82593_reconfig(dev);
-
- /* Tell the kernel that we are doing a really bad job... */
- dev->flags |= IFF_PROMISC;
}
}
else
lp->mc_count = 0;
wv_82593_reconfig(dev);
-
- /* Tell the kernel that we are doing a really bad job... */
- dev->flags |= IFF_ALLMULTI;
}
}
else
#endif
i = pcmcia_access_configuration_register(link, ®);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, AccessConfigurationRegister, i);
return FALSE;
reg.Action = CS_WRITE;
reg.Value = reg.Value | COR_SW_RESET;
i = pcmcia_access_configuration_register(link, ®);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, AccessConfigurationRegister, i);
return FALSE;
reg.Action = CS_WRITE;
reg.Value = COR_LEVEL_IRQ | COR_CONFIG;
i = pcmcia_access_configuration_register(link, ®);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, AccessConfigurationRegister, i);
return FALSE;
do
{
i = pcmcia_request_io(link, &link->io);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, RequestIO, i);
break;
* actually assign a handler to the interrupt.
*/
i = pcmcia_request_irq(link, &link->irq);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, RequestIRQ, i);
break;
*/
link->conf.ConfigIndex = 1;
i = pcmcia_request_configuration(link, &link->conf);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, RequestConfiguration, i);
break;
req.Base = req.Size = 0;
req.AccessSpeed = mem_speed;
i = pcmcia_request_window(&link, &req, &link->win);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, RequestWindow, i);
break;
mem.CardOffset = 0; mem.Page = 0;
i = pcmcia_map_mem_page(link->win, &mem);
- if(i != CS_SUCCESS)
+ if (i != 0)
{
cs_error(link, MapMemPage, i);
break;
p_dev->io.IOAddrLines = 3;
/* Interrupt setup */
- p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = wavelan_interrupt;
module_param(pc_debug, int, 0);
#define dprintk(n, format, args...) \
{ if (pc_debug > (n)) \
- printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##args); }
+ printk(KERN_INFO "%s: " format "\n", __func__ , ##args); }
#else
#define dprintk(n, format, args...)
#endif
spin_unlock_irqrestore(&this->lock, flags);
rc = wait_event_interruptible(this->wait,
this->sig_pwr_mgmt_confirm.status != 255);
- printk(KERN_INFO "%s: %s status=%d\n", __FUNCTION__,
+ printk(KERN_INFO "%s: %s status=%d\n", __func__,
suspend ? "suspend" : "resume",
this->sig_pwr_mgmt_confirm.status);
goto out;
}
WL3501_NOPLOOP(10);
}
- printk(KERN_WARNING "%s: failed to reset the board!\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: failed to reset the board!\n", __func__);
rc = -ENODEV;
out:
return rc;
out:
return rc;
fail:
- printk(KERN_WARNING "%s: failed!\n", __FUNCTION__);
+ printk(KERN_WARNING "%s: failed!\n", __func__);
goto out;
}
p_dev->io.IOAddrLines = 5;
/* Interrupt setup */
- p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+ p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;
p_dev->irq.Handler = wl3501_interrupt;
link->io.BasePort1 = j;
link->io.BasePort2 = link->io.BasePort1 + 0x10;
i = pcmcia_request_io(link, &link->io);
- if (i == CS_SUCCESS)
+ if (i == 0)
break;
}
- if (i != CS_SUCCESS) {
+ if (i != 0) {
cs_error(link, RequestIO, i);
goto failed;
}
# Makefile for the kernel pcmcia subsystem (c/o David Hinds)
#
- ifeq ($(CONFIG_PCMCIA_DEBUG),y)
- EXTRA_CFLAGS += -DDEBUG
- endif
-
pcmcia_core-y += cs.o cistpl.o rsrc_mgr.o socket_sysfs.o
pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o
obj-$(CONFIG_PCCARD) += pcmcia_core.o
obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o
obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o
obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o
-obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_core.o pxa2xx_cs.o
obj-$(CONFIG_M32R_PCC) += m32r_pcc.o
obj-$(CONFIG_M32R_CFC) += m32r_cfc.o
obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o
sa1100_cs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o
sa1100_cs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o
-pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock.o sa1111_generic.o
-pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o
-pxa2xx_cs-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o
-pxa2xx_cs-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x270.o
-pxa2xx_cs-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o
+pxa2xx_lubbock_cs-y += pxa2xx_lubbock.o sa1111_generic.o
+pxa2xx-obj-$(CONFIG_ARCH_LUBBOCK) += pxa2xx_lubbock_cs.o
+pxa2xx-obj-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o
+pxa2xx-obj-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o
+pxa2xx-obj-$(CONFIG_MACH_ARMCORE) += pxa2xx_cm_x2xx.o pxa2xx_cm_x255.o pxa2xx_cm_x270.o
+pxa2xx-obj-$(CONFIG_ARCH_VIPER) += pxa2xx_viper.o
+pxa2xx-obj-$(CONFIG_TRIZEPS_PCMCIA) += pxa2xx_trizeps.o
+pxa2xx-obj-$(CONFIG_MACH_PALMTX) += pxa2xx_palmtx.o
+pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o
+obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_core.o $(pxa2xx-obj-y)
#include <pcmcia/ss.h>
#include "cs_internal.h"
- #include "ds_internal.h"
/*====================================================================*/
MODULE_DESCRIPTION("PCMCIA Driver Services");
MODULE_LICENSE("GPL");
- #ifdef DEBUG
+ #ifdef CONFIG_PCMCIA_DEBUG
int ds_pc_debug;
module_param_named(pc_debug, ds_pc_debug, int, 0644);
#define ds_dbg(lvl, fmt, arg...) do { \
- if (ds_pc_debug > (lvl)) \
+ if (ds_pc_debug > (lvl)) \
printk(KERN_DEBUG "ds: " fmt , ## arg); \
} while (0)
+ #define ds_dev_dbg(lvl, dev, fmt, arg...) do { \
+ if (ds_pc_debug > (lvl)) \
+ dev_printk(KERN_DEBUG, dev, "ds: " fmt , ## arg); \
+ } while (0)
#else
#define ds_dbg(lvl, fmt, arg...) do { } while (0)
+ #define ds_dev_dbg(lvl, dev, fmt, arg...) do { } while (0)
#endif
spinlock_t pcmcia_dev_list_lock;
/* String tables for error messages */
typedef struct lookup_t {
- int key;
- char *msg;
+ const int key;
+ const char *msg;
} lookup_t;
static const lookup_t error_table[] = {
- { CS_SUCCESS, "Operation succeeded" },
- { CS_BAD_ADAPTER, "Bad adapter" },
- { CS_BAD_ATTRIBUTE, "Bad attribute", },
- { CS_BAD_BASE, "Bad base address" },
- { CS_BAD_EDC, "Bad EDC" },
- { CS_BAD_IRQ, "Bad IRQ" },
- { CS_BAD_OFFSET, "Bad offset" },
- { CS_BAD_PAGE, "Bad page number" },
- { CS_READ_FAILURE, "Read failure" },
- { CS_BAD_SIZE, "Bad size" },
- { CS_BAD_SOCKET, "Bad socket" },
- { CS_BAD_TYPE, "Bad type" },
- { CS_BAD_VCC, "Bad Vcc" },
- { CS_BAD_VPP, "Bad Vpp" },
- { CS_BAD_WINDOW, "Bad window" },
- { CS_WRITE_FAILURE, "Write failure" },
- { CS_NO_CARD, "No card present" },
- { CS_UNSUPPORTED_FUNCTION, "Usupported function" },
- { CS_UNSUPPORTED_MODE, "Unsupported mode" },
- { CS_BAD_SPEED, "Bad speed" },
- { CS_BUSY, "Resource busy" },
- { CS_GENERAL_FAILURE, "General failure" },
- { CS_WRITE_PROTECTED, "Write protected" },
- { CS_BAD_ARG_LENGTH, "Bad argument length" },
- { CS_BAD_ARGS, "Bad arguments" },
- { CS_CONFIGURATION_LOCKED, "Configuration locked" },
- { CS_IN_USE, "Resource in use" },
- { CS_NO_MORE_ITEMS, "No more items" },
- { CS_OUT_OF_RESOURCE, "Out of resource" },
- { CS_BAD_HANDLE, "Bad handle" },
- { CS_BAD_TUPLE, "Bad CIS tuple" }
+ { 0, "Operation succeeded" },
+ { -EIO, "Input/Output error" },
+ { -ENODEV, "No card present" },
+ { -EINVAL, "Bad parameter" },
+ { -EACCES, "Configuration locked" },
+ { -EBUSY, "Resource in use" },
+ { -ENOSPC, "No more items" },
+ { -ENOMEM, "Out of resource" },
};
{ ReplaceCIS, "ReplaceCIS" }
};
-
- static int pcmcia_report_error(struct pcmcia_device *p_dev, error_info_t *err)
+ const char *pcmcia_error_func(int func)
{
int i;
- char *serv;
-
- if (!p_dev)
- printk(KERN_NOTICE);
- else
- printk(KERN_NOTICE "%s: ", p_dev->dev.bus_id);
for (i = 0; i < ARRAY_SIZE(service_table); i++)
- if (service_table[i].key == err->func)
- break;
- if (i < ARRAY_SIZE(service_table))
- serv = service_table[i].msg;
- else
- serv = "Unknown service number";
+ if (service_table[i].key == func)
+ return service_table[i].msg;
- for (i = 0; i < ARRAY_SIZE(error_table); i++)
- if (error_table[i].key == err->retcode)
- break;
- if (i < ARRAY_SIZE(error_table))
- printk("%s: %s\n", serv, error_table[i].msg);
- else
- printk("%s: Unknown error code %#x\n", serv, err->retcode);
+ return "Unknown service number";
+ }
+ EXPORT_SYMBOL(pcmcia_error_func);
- return CS_SUCCESS;
- } /* report_error */
+ const char *pcmcia_error_ret(int ret)
+ {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(error_table); i++)
+ if (error_table[i].key == ret)
+ return error_table[i].msg;
- /* end of code which was in cs.c before */
+ return "unknown";
+ }
+ EXPORT_SYMBOL(pcmcia_error_ret);
/*======================================================================*/
- void cs_error(struct pcmcia_device *p_dev, int func, int ret)
- {
- error_info_t err = { func, ret };
- pcmcia_report_error(p_dev, &err);
- }
- EXPORT_SYMBOL(cs_error);
static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
static void pcmcia_release_dev(struct device *dev)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
- ds_dbg(1, "releasing device %s\n", p_dev->dev.bus_id);
+ ds_dev_dbg(1, dev, "releasing device\n");
pcmcia_put_socket(p_dev->socket);
kfree(p_dev->devname);
kref_put(&p_dev->function_config->ref, pcmcia_release_function);
static void pcmcia_add_device_later(struct pcmcia_socket *s, int mfc)
{
if (!s->pcmcia_state.device_add_pending) {
- ds_dbg(1, "scheduling to add %s secondary"
+ ds_dev_dbg(1, &s->dev, "scheduling to add %s secondary"
" device to %d\n", mfc ? "mfc" : "pfc", s->sock);
s->pcmcia_state.device_add_pending = 1;
s->pcmcia_state.mfc_pfc = mfc;
p_drv = to_pcmcia_drv(dev->driver);
s = p_dev->socket;
- ds_dbg(1, "trying to bind %s to %s\n", p_dev->dev.bus_id,
- p_drv->drv.name);
+ /* The PCMCIA code passes the match data in via dev->driver_data
+ * which is an ugly hack. Once the driver probe is called it may
+ * and often will overwrite the match data so we must save it first
+ *
+ * handle pseudo multifunction devices:
+ * there are at most two pseudo multifunction devices.
+ * if we're matching against the first, schedule a
+ * call which will then check whether there are two
+ * pseudo devices, and if not, add the second one.
+ */
+ did = p_dev->dev.driver_data;
+
+ ds_dev_dbg(1, dev, "trying to bind to %s\n", p_drv->drv.name);
if ((!p_drv->probe) || (!p_dev->function_config) ||
(!try_module_get(p_drv->owner))) {
p_dev->conf.ConfigBase = cis_config.base;
p_dev->conf.Present = cis_config.rmask[0];
} else {
- printk(KERN_INFO "pcmcia: could not parse base and rmask0 of CIS\n");
+ dev_printk(KERN_INFO, dev,
+ "pcmcia: could not parse base and rmask0 of CIS\n");
p_dev->conf.ConfigBase = 0;
p_dev->conf.Present = 0;
}
ret = p_drv->probe(p_dev);
if (ret) {
- ds_dbg(1, "binding %s to %s failed with %d\n",
- p_dev->dev.bus_id, p_drv->drv.name, ret);
+ ds_dev_dbg(1, dev, "binding to %s failed with %d\n",
+ p_drv->drv.name, ret);
goto put_module;
}
- /* handle pseudo multifunction devices:
- * there are at most two pseudo multifunction devices.
- * if we're matching against the first, schedule a
- * call which will then check whether there are two
- * pseudo devices, and if not, add the second one.
- */
- did = p_dev->dev.driver_data;
if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
(p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
pcmcia_add_device_later(p_dev->socket, 0);
- put_module:
+put_module:
if (ret)
module_put(p_drv->owner);
- put_dev:
+put_dev:
if (ret)
put_device(dev);
return (ret);
struct pcmcia_device *tmp;
unsigned long flags;
- ds_dbg(2, "pcmcia_card_remove(%d) %s\n", s->sock,
- leftover ? leftover->devname : "");
+ ds_dev_dbg(2, leftover ? &leftover->dev : &s->dev,
+ "pcmcia_card_remove(%d) %s\n", s->sock,
+ leftover ? leftover->devname : "");
if (!leftover)
s->device_count = 0;
p_dev->_removed=1;
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
- ds_dbg(2, "unregistering device %s\n", p_dev->dev.bus_id);
+ ds_dev_dbg(2, &p_dev->dev, "unregistering device\n");
device_unregister(&p_dev->dev);
}
p_dev = to_pcmcia_dev(dev);
p_drv = to_pcmcia_drv(dev->driver);
- ds_dbg(1, "removing device %s\n", p_dev->dev.bus_id);
+ ds_dev_dbg(1, dev, "removing device\n");
/* If we're removing the primary module driving a
* pseudo multi-function card, we need to unbind
/* check for proper unloading */
if (p_dev->_irq || p_dev->_io || p_dev->_locked)
- printk(KERN_INFO "pcmcia: driver %s did not release config properly\n",
- p_drv->drv.name);
+ dev_printk(KERN_INFO, dev,
+ "pcmcia: driver %s did not release config properly\n",
+ p_drv->drv.name);
for (i = 0; i < MAX_WIN; i++)
if (p_dev->_win & CLIENT_WIN_REQ(i))
- printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
- p_drv->drv.name);
+ dev_printk(KERN_INFO, dev,
+ "pcmcia: driver %s did not release window properly\n",
+ p_drv->drv.name);
/* references from pcmcia_probe_device */
pcmcia_put_dev(p_dev);
}
if (!pccard_read_tuple(p_dev->socket, p_dev->func,
CISTPL_DEVICE_GEO, devgeo)) {
- ds_dbg(0, "mem device geometry probably means "
- "FUNCID_MEMORY\n");
+ ds_dev_dbg(0, &p_dev->dev,
+ "mem device geometry probably means "
+ "FUNCID_MEMORY\n");
p_dev->func_id = CISTPL_FUNCID_MEMORY;
p_dev->has_func_id = 1;
}
if (!p_dev->devname)
goto err_free;
sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
- ds_dbg(3, "devname is %s\n", p_dev->devname);
+ ds_dev_dbg(3, &p_dev->dev, "devname is %s\n", p_dev->devname);
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
if (!p_dev->function_config) {
- ds_dbg(3, "creating config_t for %s\n", p_dev->dev.bus_id);
+ ds_dev_dbg(3, &p_dev->dev, "creating config_t\n");
p_dev->function_config = kzalloc(sizeof(struct config_t),
GFP_KERNEL);
if (!p_dev->function_config)
kref_init(&p_dev->function_config->ref);
}
- printk(KERN_NOTICE "pcmcia: registering new device %s\n",
- p_dev->devname);
+ dev_printk(KERN_NOTICE, &p_dev->dev,
+ "pcmcia: registering new device %s\n",
+ p_dev->devname);
pcmcia_device_query(p_dev);
int ret = 0;
if (!(s->resource_setup_done)) {
- ds_dbg(3, "no resources available, delaying card_add\n");
+ ds_dev_dbg(3, &s->dev,
+ "no resources available, delaying card_add\n");
return -EAGAIN; /* try again, but later... */
}
if (pcmcia_validate_mem(s)) {
- ds_dbg(3, "validating mem resources failed, "
+ ds_dev_dbg(3, &s->dev, "validating mem resources failed, "
"delaying card_add\n");
return -EAGAIN; /* try again, but later... */
}
ret = pccard_validate_cis(s, BIND_FN_ALL, &no_chains);
if (ret || !no_chains) {
- ds_dbg(0, "invalid CIS or invalid resources\n");
+ ds_dev_dbg(0, &s->dev, "invalid CIS or invalid resources\n");
return -ENODEV;
}
{
struct pcmcia_socket *s =
container_of(work, struct pcmcia_socket, device_add);
- ds_dbg(1, "adding additional device to %d\n", s->sock);
+ ds_dev_dbg(1, &s->dev, "adding additional device to %d\n", s->sock);
pcmcia_device_add(s, s->pcmcia_state.mfc_pfc);
s->pcmcia_state.device_add_pending = 0;
s->pcmcia_state.mfc_pfc = 0;
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
if (!p_dev->dev.driver) {
- ds_dbg(1, "update device information for %s\n",
- p_dev->dev.bus_id);
+ ds_dev_dbg(1, dev, "update device information\n");
pcmcia_device_query(p_dev);
}
unsigned long flags;
/* must be called with skt_mutex held */
- ds_dbg(0, "re-scanning socket %d\n", skt->sock);
+ ds_dev_dbg(0, &skt->dev, "re-scanning socket %d\n", skt->sock);
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
if (list_empty(&skt->devices_list))
int ret = -ENOMEM;
int no_funcs;
int old_funcs;
- cisdump_t *cis;
cistpl_longlink_mfc_t mfc;
if (!filename)
return -EINVAL;
- ds_dbg(1, "trying to load CIS file %s\n", filename);
+ ds_dev_dbg(1, &dev->dev, "trying to load CIS file %s\n", filename);
if (strlen(filename) > (FIRMWARE_NAME_MAX - 1)) {
- printk(KERN_WARNING "pcmcia: CIS filename is too long [%s]\n",
- filename);
+ dev_printk(KERN_WARNING, &dev->dev,
+ "pcmcia: CIS filename is too long [%s]\n",
+ filename);
return -EINVAL;
}
if (request_firmware(&fw, path, &dev->dev) == 0) {
if (fw->size >= CISTPL_MAX_CIS_SIZE) {
ret = -EINVAL;
- printk(KERN_ERR "pcmcia: CIS override is too big\n");
+ dev_printk(KERN_ERR, &dev->dev,
+ "pcmcia: CIS override is too big\n");
goto release;
}
- cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
- if (!cis) {
- ret = -ENOMEM;
- goto release;
- }
-
- cis->Length = fw->size + 1;
- memcpy(cis->Data, fw->data, fw->size);
-
- if (!pcmcia_replace_cis(s, cis))
+ if (!pcmcia_replace_cis(s, fw->data, fw->size))
ret = 0;
else {
- printk(KERN_ERR "pcmcia: CIS override failed\n");
+ dev_printk(KERN_ERR, &dev->dev,
+ "pcmcia: CIS override failed\n");
goto release;
}
* after it has re-checked that there is no possible module
* with a prod_id/manf_id/card_id match.
*/
- ds_dbg(0, "skipping FUNC_ID match for %s until userspace "
- "interaction\n", dev->dev.bus_id);
+ ds_dev_dbg(0, &dev->dev,
+ "skipping FUNC_ID match until userspace interaction\n");
if (!dev->allow_func_id_match)
return 0;
}
if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) {
- ds_dbg(0, "device %s needs a fake CIS\n", dev->dev.bus_id);
+ ds_dev_dbg(0, &dev->dev, "device needs a fake CIS\n");
if (!dev->socket->fake_cis)
pcmcia_load_firmware(dev, did->cisfile);
/* match dynamic devices first */
spin_lock(&p_drv->dynids.lock);
list_for_each_entry(dynid, &p_drv->dynids.list, node) {
- ds_dbg(3, "trying to match %s to %s\n", dev->bus_id,
- drv->name);
+ ds_dev_dbg(3, dev, "trying to match to %s\n", drv->name);
if (pcmcia_devmatch(p_dev, &dynid->id)) {
- ds_dbg(0, "matched %s to %s\n", dev->bus_id,
- drv->name);
+ ds_dev_dbg(0, dev, "matched to %s\n", drv->name);
spin_unlock(&p_drv->dynids.lock);
return 1;
}
#ifdef CONFIG_PCMCIA_IOCTL
/* matching by cardmgr */
if (p_dev->cardmgr == p_drv) {
- ds_dbg(0, "cardmgr matched %s to %s\n", dev->bus_id,
- drv->name);
+ ds_dev_dbg(0, dev, "cardmgr matched to %s\n", drv->name);
return 1;
}
#endif
while (did && did->match_flags) {
- ds_dbg(3, "trying to match %s to %s\n", dev->bus_id,
- drv->name);
+ ds_dev_dbg(3, dev, "trying to match to %s\n", drv->name);
if (pcmcia_devmatch(p_dev, did)) {
- ds_dbg(0, "matched %s to %s\n", dev->bus_id,
- drv->name);
+ ds_dev_dbg(0, dev, "matched to %s\n", drv->name);
return 1;
}
did++;
if (p_dev->suspended)
return 0;
- ds_dbg(2, "suspending %s\n", dev->bus_id);
+ ds_dev_dbg(2, dev, "suspending\n");
if (dev->driver)
p_drv = to_pcmcia_drv(dev->driver);
if (p_drv->suspend) {
ret = p_drv->suspend(p_dev);
if (ret) {
- printk(KERN_ERR "pcmcia: device %s (driver %s) did "
- "not want to go to sleep (%d)\n",
- p_dev->devname, p_drv->drv.name, ret);
+ dev_printk(KERN_ERR, dev,
+ "pcmcia: device %s (driver %s) did "
+ "not want to go to sleep (%d)\n",
+ p_dev->devname, p_drv->drv.name, ret);
goto out;
}
}
if (p_dev->device_no == p_dev->func) {
- ds_dbg(2, "releasing configuration for %s\n", dev->bus_id);
+ ds_dev_dbg(2, dev, "releasing configuration\n");
pcmcia_release_configuration(p_dev);
}
if (!p_dev->suspended)
return 0;
- ds_dbg(2, "resuming %s\n", dev->bus_id);
+ ds_dev_dbg(2, dev, "resuming\n");
if (dev->driver)
p_drv = to_pcmcia_drv(dev->driver);
goto out;
if (p_dev->device_no == p_dev->func) {
- ds_dbg(2, "requesting configuration for %s\n", dev->bus_id);
+ ds_dev_dbg(2, dev, "requesting configuration\n");
ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
if (ret)
goto out;
static int pcmcia_bus_resume(struct pcmcia_socket *skt)
{
- ds_dbg(2, "resuming socket %d\n", skt->sock);
+ ds_dev_dbg(2, &skt->dev, "resuming socket %d\n", skt->sock);
bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback);
return 0;
}
static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
{
- ds_dbg(2, "suspending socket %d\n", skt->sock);
+ ds_dev_dbg(2, &skt->dev, "suspending socket %d\n", skt->sock);
if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt,
pcmcia_bus_suspend_callback)) {
pcmcia_bus_resume(skt);
struct pcmcia_socket *s = pcmcia_get_socket(skt);
if (!s) {
- printk(KERN_ERR "PCMCIA obtaining reference to socket %p " \
- "failed, event 0x%x lost!\n", skt, event);
+ dev_printk(KERN_ERR, &skt->dev,
+ "PCMCIA obtaining reference to socket " \
+ "failed, event 0x%x lost!\n", event);
return -ENODEV;
}
- ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
- event, priority, skt);
+ ds_dev_dbg(1, &skt->dev, "ds_event(0x%06x, %d, 0x%p)\n",
+ event, priority, skt);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
socket = pcmcia_get_socket(socket);
if (!socket) {
- printk(KERN_ERR "PCMCIA obtaining reference to socket %p failed\n", socket);
+ dev_printk(KERN_ERR, dev,
+ "PCMCIA obtaining reference to socket failed\n");
return -ENODEV;
}
ret = pccard_register_pcmcia(socket, &pcmcia_bus_callback);
if (ret) {
- printk(KERN_ERR "PCMCIA registration PCCard core failed for socket %p\n", socket);
+ dev_printk(KERN_ERR, dev, "PCMCIA registration failed\n");
pcmcia_put_socket(socket);
return (ret);
}
#include <linux/spinlock.h>
#include <linux/platform_device.h>
-#include <asm/hardware.h>
+#include <mach/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
-#include <asm/arch/pxa-regs.h>
-#include <asm/arch/pxa2xx-regs.h>
+#include <mach/pxa-regs.h>
+#include <mach/pxa2xx-regs.h>
+#include <asm/mach-types.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
#include <pcmcia/cistpl.h>
- #include "cs_internal.h"
#include "soc_common.h"
#include "pxa2xx_base.h"
}
#endif
+static void pxa2xx_configure_sockets(struct device *dev)
+{
+ struct pcmcia_low_level *ops = dev->platform_data;
+
+ /*
+ * We have at least one socket, so set MECR:CIT
+ * (Card Is There)
+ */
+ MECR |= MECR_CIT;
+
+ /* Set MECR:NOS (Number Of Sockets) */
+ if (ops->nr > 1 || machine_is_viper())
+ MECR |= MECR_NOS;
+ else
+ MECR &= ~MECR_NOS;
+}
+
int __pxa2xx_drv_pcmcia_probe(struct device *dev)
{
int ret;
struct pcmcia_low_level *ops;
- int first, nr;
if (!dev || !dev->platform_data)
return -ENODEV;
ops = (struct pcmcia_low_level *)dev->platform_data;
- first = ops->first;
- nr = ops->nr;
/* Provide our PXA2xx specific timing routines. */
ops->set_timing = pxa2xx_pcmcia_set_timing;
ops->frequency_change = pxa2xx_pcmcia_frequency_change;
#endif
- ret = soc_common_drv_pcmcia_probe(dev, ops, first, nr);
+ ret = soc_common_drv_pcmcia_probe(dev, ops, ops->first, ops->nr);
- if (ret == 0) {
- /*
- * We have at least one socket, so set MECR:CIT
- * (Card Is There)
- */
- MECR |= MECR_CIT;
-
- /* Set MECR:NOS (Number Of Sockets) */
- if (nr > 1)
- MECR |= MECR_NOS;
- else
- MECR &= ~MECR_NOS;
- }
+ if (!ret)
+ pxa2xx_configure_sockets(dev);
return ret;
}
static int pxa2xx_drv_pcmcia_resume(struct platform_device *dev)
{
- struct pcmcia_low_level *ops = dev->dev.platform_data;
- int nr = ops ? ops->nr : 0;
-
- MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0);
-
+ pxa2xx_configure_sockets(&dev->dev);
return pcmcia_socket_dev_resume(&dev->dev);
}
static int add_interval(struct resource_map *map, u_long base, u_long num)
{
- struct resource_map *p, *q;
+ struct resource_map *p, *q;
- for (p = map; ; p = p->next) {
- if ((p != map) && (p->base+p->num-1 >= base))
- return -1;
- if ((p->next == map) || (p->next->base > base+num-1))
- break;
- }
- q = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
- if (!q) return CS_OUT_OF_RESOURCE;
- q->base = base; q->num = num;
- q->next = p->next; p->next = q;
- return CS_SUCCESS;
+ for (p = map; ; p = p->next) {
+ if ((p != map) && (p->base+p->num-1 >= base))
+ return -1;
+ if ((p->next == map) || (p->next->base > base+num-1))
+ break;
+ }
+ q = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
+ if (!q) {
+ printk(KERN_WARNING "out of memory to update resources\n");
+ return -ENOMEM;
+ }
+ q->base = base; q->num = num;
+ q->next = p->next; p->next = q;
+ return 0;
}
/*====================================================================*/
} else {
/* Split the block into two pieces */
p = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
- if (!p) return CS_OUT_OF_RESOURCE;
+ if (!p) {
+ printk(KERN_WARNING "out of memory to update resources\n");
+ return -ENOMEM;
+ }
p->base = base+num;
p->num = q->base+q->num - p->base;
q->num = base - q->base;
}
}
}
- return CS_SUCCESS;
+ return 0;
}
/*======================================================================
int any;
u_char *b, hole, most;
- printk(KERN_INFO "cs: IO port probe %#x-%#x:",
- base, base+num-1);
+ dev_printk(KERN_INFO, &s->dev, "cs: IO port probe %#x-%#x:",
+ base, base+num-1);
/* First, what does a floating port look like? */
b = kzalloc(256, GFP_KERNEL);
if (!b) {
- printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
+ dev_printk(KERN_ERR, &s->dev,
+ "do_io_probe: unable to kmalloc 256 bytes");
return;
}
for (i = base, most = 0; i < base+num; i += 8) {
destroy_cis_cache(s);
}
s->cis_mem.res = NULL;
- if ((ret != 0) || (count == 0))
+ if ((ret != 0) || (*count == 0))
return 0;
return 1;
}
struct socket_data *s_data = s->resource_data;
u_long i, j, bad, fail, step;
- printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
- base, base+num-1);
+ dev_printk(KERN_INFO, &s->dev, "cs: memory probe 0x%06lx-0x%06lx:",
+ base, base+num-1);
bad = fail = 0;
step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
/* don't allow too large steps */
if (probe_mask & MEM_PROBE_HIGH) {
if (inv_probe(s_data->mem_db.next, s) > 0)
return 0;
- printk(KERN_NOTICE "cs: warning: no high memory space "
- "available!\n");
+ dev_printk(KERN_NOTICE, &s->dev,
+ "cs: warning: no high memory space available!\n");
return -ENODEV;
}
if (res->flags & IORESOURCE_IO) {
if (res == &ioport_resource)
continue;
- printk(KERN_INFO "pcmcia: parent PCI bridge I/O "
- "window: 0x%llx - 0x%llx\n",
- (unsigned long long)res->start,
- (unsigned long long)res->end);
+ dev_printk(KERN_INFO, &s->cb_dev->dev,
+ "pcmcia: parent PCI bridge I/O "
+ "window: 0x%llx - 0x%llx\n",
+ (unsigned long long)res->start,
+ (unsigned long long)res->end);
if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end))
done |= IORESOURCE_IO;
if (res->flags & IORESOURCE_MEM) {
if (res == &iomem_resource)
continue;
- printk(KERN_INFO "pcmcia: parent PCI bridge Memory "
- "window: 0x%llx - 0x%llx\n",
- (unsigned long long)res->start,
- (unsigned long long)res->end);
+ dev_printk(KERN_INFO, &s->cb_dev->dev,
+ "pcmcia: parent PCI bridge Memory "
+ "window: 0x%llx - 0x%llx\n",
+ (unsigned long long)res->start,
+ (unsigned long long)res->end);
if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end))
done |= IORESOURCE_MEM;
}
#include <linux/spinlock.h>
#include <linux/cpufreq.h>
-#include <asm/hardware.h>
+#include <mach/hardware.h>
#include <asm/io.h>
#include <asm/system.h>
/* FIXME: platform dependent resource declaration has to move out of this file */
#ifdef CONFIG_ARCH_PXA
-#include <asm/arch/pxa-regs.h>
+#include <mach/pxa-regs.h>
#endif
- #ifdef DEBUG
+ #ifdef CONFIG_PCMCIA_DEBUG
static int pc_debug;
module_param(pc_debug, int, 0644);
add_timer(&skt->poll_timer);
- device_create_file(&skt->socket.dev, &dev_attr_status);
+ ret = device_create_file(&skt->socket.dev, &dev_attr_status);
+ if (ret)
+ goto out_err_8;
}
dev_set_drvdata(dev, sinfo);
do {
skt = &sinfo->skt[i];
+ device_remove_file(&skt->socket.dev, &dev_attr_status);
+ out_err_8:
del_timer_sync(&skt->poll_timer);
pcmcia_unregister_socket(&skt->socket);
***********************************************************************/
-#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
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 int nsp_cs_config(struct pcmcia_device *link)
- {
- int ret;
- 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;
-
- nsp_dbg(NSP_DEBUG_INIT, "in");
-
- tuple.Attributes = 0;
- tuple.TupleData = tuple_data;
- tuple.TupleDataMax = sizeof(tuple_data);
- tuple.TupleOffset = 0;
-
- /* Look up the current Vcc */
- CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
- tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
- CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
- while (1) {
- cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+ struct nsp_cs_configdata {
+ nsp_hw_data *data;
+ win_req_t req;
+ };
- if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
- pcmcia_parse_tuple(link, &tuple, &parse) != 0)
- goto next_entry;
+ 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)
+ {
+ struct nsp_cs_configdata *cfg_mem = priv_data;
- if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { dflt = *cfg; }
- if (cfg->index == 0) { goto next_entry; }
- link->conf.ConfigIndex = cfg->index;
+ if (cfg->index == 0)
+ return -ENODEV;
- /* 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, &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, &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(link);
- CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &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, &link->irq));
+ if (pcmcia_request_irq(link, &link->irq))
+ goto cs_failed;
}
- CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
+
+ ret = pcmcia_request_configuration(link, &link->conf);
+ if (ret)
+ goto cs_failed;
if (free_ports) {
if (link->io.BasePort1) {
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");
+ kfree(cfg_mem);
return 0;
cs_failed:
nsp_dbg(NSP_DEBUG_INIT, "config fail");
- cs_error(link, last_fn, last_ret);
nsp_cs_release(link);
+ kfree(cfg_mem);
return -ENODEV;
} /* nsp_cs_config */
- #undef CS_CHECK
/*======================================================================