Merge branch 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6
* 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6: pcmcia pcnet_cs: try setting io_lines to 16 if card setup fails pcmcia: per-device, not per-socket debug messages pcmcia serial_cs.c: fix multifunction card handling
This commit is contained in:
commit
bd12e5c3a1
|
@ -508,7 +508,8 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev,
|
||||||
unsigned int vcc,
|
unsigned int vcc,
|
||||||
void *priv_data)
|
void *priv_data)
|
||||||
{
|
{
|
||||||
int *has_shmem = priv_data;
|
int *priv = priv_data;
|
||||||
|
int try = (*priv & 0x1);
|
||||||
int i;
|
int i;
|
||||||
cistpl_io_t *io = &cfg->io;
|
cistpl_io_t *io = &cfg->io;
|
||||||
|
|
||||||
|
@ -525,77 +526,103 @@ static int pcnet_confcheck(struct pcmcia_device *p_dev,
|
||||||
i = p_dev->resource[1]->end = 0;
|
i = p_dev->resource[1]->end = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
*has_shmem = ((cfg->mem.nwin == 1) &&
|
*priv &= ((cfg->mem.nwin == 1) &&
|
||||||
(cfg->mem.win[0].len >= 0x4000));
|
(cfg->mem.win[0].len >= 0x4000)) ? 0x10 : ~0x10;
|
||||||
|
|
||||||
p_dev->resource[0]->start = io->win[i].base;
|
p_dev->resource[0]->start = io->win[i].base;
|
||||||
p_dev->resource[0]->end = io->win[i].len;
|
p_dev->resource[0]->end = io->win[i].len;
|
||||||
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
|
if (!try)
|
||||||
|
p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
|
||||||
|
else
|
||||||
|
p_dev->io_lines = 16;
|
||||||
if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
|
if (p_dev->resource[0]->end + p_dev->resource[1]->end >= 32)
|
||||||
return try_io_port(p_dev);
|
return try_io_port(p_dev);
|
||||||
|
|
||||||
return 0;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static hw_info_t *pcnet_try_config(struct pcmcia_device *link,
|
||||||
|
int *has_shmem, int try)
|
||||||
|
{
|
||||||
|
struct net_device *dev = link->priv;
|
||||||
|
hw_info_t *local_hw_info;
|
||||||
|
pcnet_dev_t *info = PRIV(dev);
|
||||||
|
int priv = try;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = pcmcia_loop_config(link, pcnet_confcheck, &priv);
|
||||||
|
if (ret) {
|
||||||
|
dev_warn(&link->dev, "no useable port range found\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
*has_shmem = (priv & 0x10);
|
||||||
|
|
||||||
|
if (!link->irq)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (resource_size(link->resource[1]) == 8) {
|
||||||
|
link->conf.Attributes |= CONF_ENABLE_SPKR;
|
||||||
|
link->conf.Status = CCSR_AUDIO_ENA;
|
||||||
|
}
|
||||||
|
if ((link->manf_id == MANFID_IBM) &&
|
||||||
|
(link->card_id == PRODID_IBM_HOME_AND_AWAY))
|
||||||
|
link->conf.ConfigIndex |= 0x10;
|
||||||
|
|
||||||
|
ret = pcmcia_request_configuration(link, &link->conf);
|
||||||
|
if (ret)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
dev->irq = link->irq;
|
||||||
|
dev->base_addr = link->resource[0]->start;
|
||||||
|
|
||||||
|
if (info->flags & HAS_MISC_REG) {
|
||||||
|
if ((if_port == 1) || (if_port == 2))
|
||||||
|
dev->if_port = if_port;
|
||||||
|
else
|
||||||
|
dev_notice(&link->dev, "invalid if_port requested\n");
|
||||||
|
} else
|
||||||
|
dev->if_port = 0;
|
||||||
|
|
||||||
|
if ((link->conf.ConfigBase == 0x03c0) &&
|
||||||
|
(link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
|
||||||
|
dev_info(&link->dev,
|
||||||
|
"this is an AX88190 card - use axnet_cs instead.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
local_hw_info = get_hwinfo(link);
|
||||||
|
if (!local_hw_info)
|
||||||
|
local_hw_info = get_prom(link);
|
||||||
|
if (!local_hw_info)
|
||||||
|
local_hw_info = get_dl10019(link);
|
||||||
|
if (!local_hw_info)
|
||||||
|
local_hw_info = get_ax88190(link);
|
||||||
|
if (!local_hw_info)
|
||||||
|
local_hw_info = get_hwired(link);
|
||||||
|
|
||||||
|
return local_hw_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pcnet_config(struct pcmcia_device *link)
|
static int pcnet_config(struct pcmcia_device *link)
|
||||||
{
|
{
|
||||||
struct net_device *dev = link->priv;
|
struct net_device *dev = link->priv;
|
||||||
pcnet_dev_t *info = PRIV(dev);
|
pcnet_dev_t *info = PRIV(dev);
|
||||||
int ret, start_pg, stop_pg, cm_offset;
|
int start_pg, stop_pg, cm_offset;
|
||||||
int has_shmem = 0;
|
int has_shmem = 0;
|
||||||
hw_info_t *local_hw_info;
|
hw_info_t *local_hw_info;
|
||||||
|
|
||||||
dev_dbg(&link->dev, "pcnet_config\n");
|
dev_dbg(&link->dev, "pcnet_config\n");
|
||||||
|
|
||||||
ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem);
|
local_hw_info = pcnet_try_config(link, &has_shmem, 0);
|
||||||
if (ret)
|
if (!local_hw_info) {
|
||||||
goto failed;
|
/* check whether forcing io_lines to 16 helps... */
|
||||||
|
pcmcia_disable_device(link);
|
||||||
if (!link->irq)
|
local_hw_info = pcnet_try_config(link, &has_shmem, 1);
|
||||||
goto failed;
|
if (local_hw_info == NULL) {
|
||||||
|
dev_notice(&link->dev, "unable to read hardware net"
|
||||||
if (resource_size(link->resource[1]) == 8) {
|
" address for io base %#3lx\n", dev->base_addr);
|
||||||
link->conf.Attributes |= CONF_ENABLE_SPKR;
|
goto failed;
|
||||||
link->conf.Status = CCSR_AUDIO_ENA;
|
}
|
||||||
}
|
|
||||||
if ((link->manf_id == MANFID_IBM) &&
|
|
||||||
(link->card_id == PRODID_IBM_HOME_AND_AWAY))
|
|
||||||
link->conf.ConfigIndex |= 0x10;
|
|
||||||
|
|
||||||
ret = pcmcia_request_configuration(link, &link->conf);
|
|
||||||
if (ret)
|
|
||||||
goto failed;
|
|
||||||
dev->irq = link->irq;
|
|
||||||
dev->base_addr = link->resource[0]->start;
|
|
||||||
if (info->flags & HAS_MISC_REG) {
|
|
||||||
if ((if_port == 1) || (if_port == 2))
|
|
||||||
dev->if_port = if_port;
|
|
||||||
else
|
|
||||||
printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n");
|
|
||||||
} else {
|
|
||||||
dev->if_port = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((link->conf.ConfigBase == 0x03c0) &&
|
|
||||||
(link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
|
|
||||||
printk(KERN_INFO "pcnet_cs: this is an AX88190 card!\n");
|
|
||||||
printk(KERN_INFO "pcnet_cs: use axnet_cs instead.\n");
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
local_hw_info = get_hwinfo(link);
|
|
||||||
if (local_hw_info == NULL)
|
|
||||||
local_hw_info = get_prom(link);
|
|
||||||
if (local_hw_info == NULL)
|
|
||||||
local_hw_info = get_dl10019(link);
|
|
||||||
if (local_hw_info == NULL)
|
|
||||||
local_hw_info = get_ax88190(link);
|
|
||||||
if (local_hw_info == NULL)
|
|
||||||
local_hw_info = get_hwired(link);
|
|
||||||
|
|
||||||
if (local_hw_info == NULL) {
|
|
||||||
printk(KERN_NOTICE "pcnet_cs: unable to read hardware net"
|
|
||||||
" address for io base %#3lx\n", dev->base_addr);
|
|
||||||
goto failed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
info->flags = local_hw_info->flags;
|
info->flags = local_hw_info->flags;
|
||||||
|
|
|
@ -163,7 +163,7 @@ static int pcmcia_access_config(struct pcmcia_device *p_dev,
|
||||||
c = p_dev->function_config;
|
c = p_dev->function_config;
|
||||||
|
|
||||||
if (!(c->state & CONFIG_LOCKED)) {
|
if (!(c->state & CONFIG_LOCKED)) {
|
||||||
dev_dbg(&s->dev, "Configuration isnt't locked\n");
|
dev_dbg(&p_dev->dev, "Configuration isnt't locked\n");
|
||||||
mutex_unlock(&s->ops_mutex);
|
mutex_unlock(&s->ops_mutex);
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,7 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
|
||||||
s->win[w].card_start = offset;
|
s->win[w].card_start = offset;
|
||||||
ret = s->ops->set_mem_map(s, &s->win[w]);
|
ret = s->ops->set_mem_map(s, &s->win[w]);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_warn(&s->dev, "failed to set_mem_map\n");
|
dev_warn(&p_dev->dev, "failed to set_mem_map\n");
|
||||||
mutex_unlock(&s->ops_mutex);
|
mutex_unlock(&s->ops_mutex);
|
||||||
return ret;
|
return ret;
|
||||||
} /* pcmcia_map_mem_page */
|
} /* pcmcia_map_mem_page */
|
||||||
|
@ -244,18 +244,18 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
|
||||||
c = p_dev->function_config;
|
c = p_dev->function_config;
|
||||||
|
|
||||||
if (!(s->state & SOCKET_PRESENT)) {
|
if (!(s->state & SOCKET_PRESENT)) {
|
||||||
dev_dbg(&s->dev, "No card present\n");
|
dev_dbg(&p_dev->dev, "No card present\n");
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
if (!(c->state & CONFIG_LOCKED)) {
|
if (!(c->state & CONFIG_LOCKED)) {
|
||||||
dev_dbg(&s->dev, "Configuration isnt't locked\n");
|
dev_dbg(&p_dev->dev, "Configuration isnt't locked\n");
|
||||||
ret = -EACCES;
|
ret = -EACCES;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) {
|
if (mod->Attributes & (CONF_IRQ_CHANGE_VALID | CONF_VCC_CHANGE_VALID)) {
|
||||||
dev_dbg(&s->dev,
|
dev_dbg(&p_dev->dev,
|
||||||
"changing Vcc or IRQ is not allowed at this time\n");
|
"changing Vcc or IRQ is not allowed at this time\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
@ -265,20 +265,22 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,
|
||||||
if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
|
if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&
|
||||||
(mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
|
(mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
|
||||||
if (mod->Vpp1 != mod->Vpp2) {
|
if (mod->Vpp1 != mod->Vpp2) {
|
||||||
dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n");
|
dev_dbg(&p_dev->dev,
|
||||||
|
"Vpp1 and Vpp2 must be the same\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
s->socket.Vpp = mod->Vpp1;
|
s->socket.Vpp = mod->Vpp1;
|
||||||
if (s->ops->set_socket(s, &s->socket)) {
|
if (s->ops->set_socket(s, &s->socket)) {
|
||||||
dev_printk(KERN_WARNING, &s->dev,
|
dev_printk(KERN_WARNING, &p_dev->dev,
|
||||||
"Unable to set VPP\n");
|
"Unable to set VPP\n");
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
} else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
|
} else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
|
||||||
(mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
|
(mod->Attributes & CONF_VPP2_CHANGE_VALID)) {
|
||||||
dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n");
|
dev_dbg(&p_dev->dev,
|
||||||
|
"changing Vcc is not allowed at this time\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
@ -401,7 +403,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
|
||||||
win = &s->win[w];
|
win = &s->win[w];
|
||||||
|
|
||||||
if (!(p_dev->_win & CLIENT_WIN_REQ(w))) {
|
if (!(p_dev->_win & CLIENT_WIN_REQ(w))) {
|
||||||
dev_dbg(&s->dev, "not releasing unknown window\n");
|
dev_dbg(&p_dev->dev, "not releasing unknown window\n");
|
||||||
mutex_unlock(&s->ops_mutex);
|
mutex_unlock(&s->ops_mutex);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -439,7 +441,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if (req->IntType & INT_CARDBUS) {
|
if (req->IntType & INT_CARDBUS) {
|
||||||
dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n");
|
dev_dbg(&p_dev->dev, "IntType may not be INT_CARDBUS\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,7 +449,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
|
||||||
c = p_dev->function_config;
|
c = p_dev->function_config;
|
||||||
if (c->state & CONFIG_LOCKED) {
|
if (c->state & CONFIG_LOCKED) {
|
||||||
mutex_unlock(&s->ops_mutex);
|
mutex_unlock(&s->ops_mutex);
|
||||||
dev_dbg(&s->dev, "Configuration is locked\n");
|
dev_dbg(&p_dev->dev, "Configuration is locked\n");
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,7 +457,7 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,
|
||||||
s->socket.Vpp = req->Vpp;
|
s->socket.Vpp = req->Vpp;
|
||||||
if (s->ops->set_socket(s, &s->socket)) {
|
if (s->ops->set_socket(s, &s->socket)) {
|
||||||
mutex_unlock(&s->ops_mutex);
|
mutex_unlock(&s->ops_mutex);
|
||||||
dev_printk(KERN_WARNING, &s->dev,
|
dev_printk(KERN_WARNING, &p_dev->dev,
|
||||||
"Unable to set socket state\n");
|
"Unable to set socket state\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -569,19 +571,20 @@ int pcmcia_request_io(struct pcmcia_device *p_dev)
|
||||||
int ret = -EINVAL;
|
int ret = -EINVAL;
|
||||||
|
|
||||||
mutex_lock(&s->ops_mutex);
|
mutex_lock(&s->ops_mutex);
|
||||||
dev_dbg(&s->dev, "pcmcia_request_io: %pR , %pR", &c->io[0], &c->io[1]);
|
dev_dbg(&p_dev->dev, "pcmcia_request_io: %pR , %pR",
|
||||||
|
&c->io[0], &c->io[1]);
|
||||||
|
|
||||||
if (!(s->state & SOCKET_PRESENT)) {
|
if (!(s->state & SOCKET_PRESENT)) {
|
||||||
dev_dbg(&s->dev, "pcmcia_request_io: No card present\n");
|
dev_dbg(&p_dev->dev, "pcmcia_request_io: No card present\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->state & CONFIG_LOCKED) {
|
if (c->state & CONFIG_LOCKED) {
|
||||||
dev_dbg(&s->dev, "Configuration is locked\n");
|
dev_dbg(&p_dev->dev, "Configuration is locked\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (c->state & CONFIG_IO_REQ) {
|
if (c->state & CONFIG_IO_REQ) {
|
||||||
dev_dbg(&s->dev, "IO already configured\n");
|
dev_dbg(&p_dev->dev, "IO already configured\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,7 +604,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev)
|
||||||
c->state |= CONFIG_IO_REQ;
|
c->state |= CONFIG_IO_REQ;
|
||||||
p_dev->_io = 1;
|
p_dev->_io = 1;
|
||||||
|
|
||||||
dev_dbg(&s->dev, "pcmcia_request_io succeeded: %pR , %pR",
|
dev_dbg(&p_dev->dev, "pcmcia_request_io succeeded: %pR , %pR",
|
||||||
&c->io[0], &c->io[1]);
|
&c->io[0], &c->io[1]);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&s->ops_mutex);
|
mutex_unlock(&s->ops_mutex);
|
||||||
|
@ -800,7 +803,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
||||||
int w;
|
int w;
|
||||||
|
|
||||||
if (!(s->state & SOCKET_PRESENT)) {
|
if (!(s->state & SOCKET_PRESENT)) {
|
||||||
dev_dbg(&s->dev, "No card present\n");
|
dev_dbg(&p_dev->dev, "No card present\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -809,12 +812,12 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
||||||
req->Size = s->map_size;
|
req->Size = s->map_size;
|
||||||
align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size;
|
align = (s->features & SS_CAP_MEM_ALIGN) ? req->Size : s->map_size;
|
||||||
if (req->Size & (s->map_size-1)) {
|
if (req->Size & (s->map_size-1)) {
|
||||||
dev_dbg(&s->dev, "invalid map size\n");
|
dev_dbg(&p_dev->dev, "invalid map size\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
|
if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||
|
||||||
(req->Base & (align-1))) {
|
(req->Base & (align-1))) {
|
||||||
dev_dbg(&s->dev, "invalid base address\n");
|
dev_dbg(&p_dev->dev, "invalid base address\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (req->Base)
|
if (req->Base)
|
||||||
|
@ -826,7 +829,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
||||||
if (!(s->state & SOCKET_WIN_REQ(w)))
|
if (!(s->state & SOCKET_WIN_REQ(w)))
|
||||||
break;
|
break;
|
||||||
if (w == MAX_WIN) {
|
if (w == MAX_WIN) {
|
||||||
dev_dbg(&s->dev, "all windows are used already\n");
|
dev_dbg(&p_dev->dev, "all windows are used already\n");
|
||||||
mutex_unlock(&s->ops_mutex);
|
mutex_unlock(&s->ops_mutex);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -837,7 +840,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
||||||
win->res = pcmcia_find_mem_region(req->Base, req->Size, align,
|
win->res = pcmcia_find_mem_region(req->Base, req->Size, align,
|
||||||
0, s);
|
0, s);
|
||||||
if (!win->res) {
|
if (!win->res) {
|
||||||
dev_dbg(&s->dev, "allocating mem region failed\n");
|
dev_dbg(&p_dev->dev, "allocating mem region failed\n");
|
||||||
mutex_unlock(&s->ops_mutex);
|
mutex_unlock(&s->ops_mutex);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -851,7 +854,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
||||||
win->card_start = 0;
|
win->card_start = 0;
|
||||||
|
|
||||||
if (s->ops->set_mem_map(s, win) != 0) {
|
if (s->ops->set_mem_map(s, win) != 0) {
|
||||||
dev_dbg(&s->dev, "failed to set memory mapping\n");
|
dev_dbg(&p_dev->dev, "failed to set memory mapping\n");
|
||||||
mutex_unlock(&s->ops_mutex);
|
mutex_unlock(&s->ops_mutex);
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -874,7 +877,7 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
||||||
if (win->res)
|
if (win->res)
|
||||||
request_resource(&iomem_resource, res);
|
request_resource(&iomem_resource, res);
|
||||||
|
|
||||||
dev_dbg(&s->dev, "request_window results in %pR\n", res);
|
dev_dbg(&p_dev->dev, "request_window results in %pR\n", res);
|
||||||
|
|
||||||
mutex_unlock(&s->ops_mutex);
|
mutex_unlock(&s->ops_mutex);
|
||||||
*wh = res;
|
*wh = res;
|
||||||
|
|
|
@ -335,8 +335,6 @@ static int serial_probe(struct pcmcia_device *link)
|
||||||
info->p_dev = link;
|
info->p_dev = link;
|
||||||
link->priv = info;
|
link->priv = info;
|
||||||
|
|
||||||
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
|
|
||||||
link->resource[0]->end = 8;
|
|
||||||
link->conf.Attributes = CONF_ENABLE_IRQ;
|
link->conf.Attributes = CONF_ENABLE_IRQ;
|
||||||
if (do_sound) {
|
if (do_sound) {
|
||||||
link->conf.Attributes |= CONF_ENABLE_SPKR;
|
link->conf.Attributes |= CONF_ENABLE_SPKR;
|
||||||
|
@ -411,6 +409,27 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
|
||||||
|
|
||||||
/*====================================================================*/
|
/*====================================================================*/
|
||||||
|
|
||||||
|
static int pfc_config(struct pcmcia_device *p_dev)
|
||||||
|
{
|
||||||
|
unsigned int port = 0;
|
||||||
|
struct serial_info *info = p_dev->priv;
|
||||||
|
|
||||||
|
if ((p_dev->resource[1]->end != 0) &&
|
||||||
|
(resource_size(p_dev->resource[1]) == 8)) {
|
||||||
|
port = p_dev->resource[1]->start;
|
||||||
|
info->slave = 1;
|
||||||
|
} else if ((info->manfid == MANFID_OSITECH) &&
|
||||||
|
(resource_size(p_dev->resource[0]) == 0x40)) {
|
||||||
|
port = p_dev->resource[0]->start + 0x28;
|
||||||
|
info->slave = 1;
|
||||||
|
}
|
||||||
|
if (info->slave)
|
||||||
|
return setup_serial(p_dev, info, port, p_dev->irq);
|
||||||
|
|
||||||
|
dev_warn(&p_dev->dev, "no usable port range found, giving up\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
static int simple_config_check(struct pcmcia_device *p_dev,
|
static int simple_config_check(struct pcmcia_device *p_dev,
|
||||||
cistpl_cftable_entry_t *cf,
|
cistpl_cftable_entry_t *cf,
|
||||||
cistpl_cftable_entry_t *dflt,
|
cistpl_cftable_entry_t *dflt,
|
||||||
|
@ -461,23 +480,8 @@ static int simple_config(struct pcmcia_device *link)
|
||||||
struct serial_info *info = link->priv;
|
struct serial_info *info = link->priv;
|
||||||
int i = -ENODEV, try;
|
int i = -ENODEV, try;
|
||||||
|
|
||||||
/* If the card is already configured, look up the port and irq */
|
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
|
||||||
if (link->function_config) {
|
link->resource[0]->end = 8;
|
||||||
unsigned int port = 0;
|
|
||||||
if ((link->resource[1]->end != 0) &&
|
|
||||||
(resource_size(link->resource[1]) == 8)) {
|
|
||||||
port = link->resource[1]->end;
|
|
||||||
info->slave = 1;
|
|
||||||
} else if ((info->manfid == MANFID_OSITECH) &&
|
|
||||||
(resource_size(link->resource[0]) == 0x40)) {
|
|
||||||
port = link->resource[0]->start + 0x28;
|
|
||||||
info->slave = 1;
|
|
||||||
}
|
|
||||||
if (info->slave) {
|
|
||||||
return setup_serial(link, info, port,
|
|
||||||
link->irq);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First pass: look for a config entry that looks normal.
|
/* First pass: look for a config entry that looks normal.
|
||||||
* Two tries: without IO aliases, then with aliases */
|
* Two tries: without IO aliases, then with aliases */
|
||||||
|
@ -491,8 +495,7 @@ static int simple_config(struct pcmcia_device *link)
|
||||||
if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
|
if (!pcmcia_loop_config(link, simple_config_check_notpicky, NULL))
|
||||||
goto found_port;
|
goto found_port;
|
||||||
|
|
||||||
printk(KERN_NOTICE
|
dev_warn(&link->dev, "no usable port range found, giving up\n");
|
||||||
"serial_cs: no usable port range found, giving up\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
found_port:
|
found_port:
|
||||||
|
@ -558,6 +561,7 @@ static int multi_config(struct pcmcia_device *link)
|
||||||
int i, base2 = 0;
|
int i, base2 = 0;
|
||||||
|
|
||||||
/* First, look for a generic full-sized window */
|
/* First, look for a generic full-sized window */
|
||||||
|
link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
|
||||||
link->resource[0]->end = info->multi * 8;
|
link->resource[0]->end = info->multi * 8;
|
||||||
if (pcmcia_loop_config(link, multi_config_check, &base2)) {
|
if (pcmcia_loop_config(link, multi_config_check, &base2)) {
|
||||||
/* If that didn't work, look for two windows */
|
/* If that didn't work, look for two windows */
|
||||||
|
@ -565,15 +569,14 @@ static int multi_config(struct pcmcia_device *link)
|
||||||
info->multi = 2;
|
info->multi = 2;
|
||||||
if (pcmcia_loop_config(link, multi_config_check_notpicky,
|
if (pcmcia_loop_config(link, multi_config_check_notpicky,
|
||||||
&base2)) {
|
&base2)) {
|
||||||
printk(KERN_NOTICE "serial_cs: no usable port range"
|
dev_warn(&link->dev, "no usable port range "
|
||||||
"found, giving up\n");
|
"found, giving up\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!link->irq)
|
if (!link->irq)
|
||||||
dev_warn(&link->dev,
|
dev_warn(&link->dev, "no usable IRQ found, continuing...\n");
|
||||||
"serial_cs: no usable IRQ found, continuing...\n");
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Apply any configuration quirks.
|
* Apply any configuration quirks.
|
||||||
|
@ -675,6 +678,7 @@ static int serial_config(struct pcmcia_device * link)
|
||||||
multifunction cards that ask for appropriate IO port ranges */
|
multifunction cards that ask for appropriate IO port ranges */
|
||||||
if ((info->multi == 0) &&
|
if ((info->multi == 0) &&
|
||||||
(link->has_func_id) &&
|
(link->has_func_id) &&
|
||||||
|
(link->socket->pcmcia_pfc == 0) &&
|
||||||
((link->func_id == CISTPL_FUNCID_MULTI) ||
|
((link->func_id == CISTPL_FUNCID_MULTI) ||
|
||||||
(link->func_id == CISTPL_FUNCID_SERIAL)))
|
(link->func_id == CISTPL_FUNCID_SERIAL)))
|
||||||
pcmcia_loop_config(link, serial_check_for_multi, info);
|
pcmcia_loop_config(link, serial_check_for_multi, info);
|
||||||
|
@ -685,7 +689,13 @@ static int serial_config(struct pcmcia_device * link)
|
||||||
if (info->quirk && info->quirk->multi != -1)
|
if (info->quirk && info->quirk->multi != -1)
|
||||||
info->multi = info->quirk->multi;
|
info->multi = info->quirk->multi;
|
||||||
|
|
||||||
if (info->multi > 1)
|
dev_info(&link->dev,
|
||||||
|
"trying to set up [0x%04x:0x%04x] (pfc: %d, multi: %d, quirk: %p)\n",
|
||||||
|
link->manf_id, link->card_id,
|
||||||
|
link->socket->pcmcia_pfc, info->multi, info->quirk);
|
||||||
|
if (link->socket->pcmcia_pfc)
|
||||||
|
i = pfc_config(link);
|
||||||
|
else if (info->multi > 1)
|
||||||
i = multi_config(link);
|
i = multi_config(link);
|
||||||
else
|
else
|
||||||
i = simple_config(link);
|
i = simple_config(link);
|
||||||
|
@ -704,7 +714,7 @@ static int serial_config(struct pcmcia_device * link)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed:
|
failed:
|
||||||
dev_warn(&link->dev, "serial_cs: failed to initialize\n");
|
dev_warn(&link->dev, "failed to initialize\n");
|
||||||
serial_remove(link);
|
serial_remove(link);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue