in pcmcia_resource.c [833:920]
int pcmcia_request_window(struct pcmcia_device *p_dev, struct resource *res,
unsigned int speed)
{
struct pcmcia_socket *s = p_dev->socket;
pccard_mem_map *win;
u_long align;
int w;
dev_dbg(&p_dev->dev, "request_window %pR %d\n", res, speed);
if (!(s->state & SOCKET_PRESENT)) {
dev_dbg(&p_dev->dev, "No card present\n");
return -ENODEV;
}
/* Window size defaults to smallest available */
if (res->end == 0)
res->end = s->map_size;
align = (s->features & SS_CAP_MEM_ALIGN) ? res->end : s->map_size;
if (res->end & (s->map_size-1)) {
dev_dbg(&p_dev->dev, "invalid map size\n");
return -EINVAL;
}
if ((res->start && (s->features & SS_CAP_STATIC_MAP)) ||
(res->start & (align-1))) {
dev_dbg(&p_dev->dev, "invalid base address\n");
return -EINVAL;
}
if (res->start)
align = 0;
/* Allocate system memory window */
mutex_lock(&s->ops_mutex);
for (w = 0; w < MAX_WIN; w++)
if (!(s->state & SOCKET_WIN_REQ(w)))
break;
if (w == MAX_WIN) {
dev_dbg(&p_dev->dev, "all windows are used already\n");
mutex_unlock(&s->ops_mutex);
return -EINVAL;
}
win = &s->win[w];
if (!(s->features & SS_CAP_STATIC_MAP)) {
win->res = pcmcia_find_mem_region(res->start, res->end, align,
0, s);
if (!win->res) {
dev_dbg(&p_dev->dev, "allocating mem region failed\n");
mutex_unlock(&s->ops_mutex);
return -EINVAL;
}
}
p_dev->_win |= CLIENT_WIN_REQ(w);
/* Configure the socket controller */
win->map = w+1;
win->flags = res->flags & WIN_FLAGS_MAP;
win->speed = speed;
win->card_start = 0;
if (s->ops->set_mem_map(s, win) != 0) {
dev_dbg(&p_dev->dev, "failed to set memory mapping\n");
mutex_unlock(&s->ops_mutex);
return -EIO;
}
s->state |= SOCKET_WIN_REQ(w);
/* Return window handle */
if (s->features & SS_CAP_STATIC_MAP)
res->start = win->static_start;
else
res->start = win->res->start;
/* convert to new-style resources */
res->end += res->start - 1;
res->flags &= ~WIN_FLAGS_REQ;
res->flags |= (win->map << 2) | IORESOURCE_MEM;
res->parent = win->res;
if (win->res)
request_resource(&iomem_resource, res);
dev_dbg(&p_dev->dev, "request_window results in %pR\n", res);
mutex_unlock(&s->ops_mutex);
return 0;
} /* pcmcia_request_window */