|
@@ -196,15 +196,17 @@ int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh,
|
|
unsigned int offset)
|
|
unsigned int offset)
|
|
{
|
|
{
|
|
struct pcmcia_socket *s = p_dev->socket;
|
|
struct pcmcia_socket *s = p_dev->socket;
|
|
|
|
+ struct resource *res = wh;
|
|
|
|
+ unsigned int w;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- wh--;
|
|
|
|
- if (wh >= MAX_WIN)
|
|
|
|
|
|
+ w = ((res->flags & IORESOURCE_BITS & WIN_FLAGS_REQ) >> 2) - 1;
|
|
|
|
+ if (w >= MAX_WIN)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
mutex_lock(&s->ops_mutex);
|
|
mutex_lock(&s->ops_mutex);
|
|
- s->win[wh].card_start = offset;
|
|
|
|
- ret = s->ops->set_mem_map(s, &s->win[wh]);
|
|
|
|
|
|
+ s->win[w].card_start = offset;
|
|
|
|
+ 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(&s->dev, "failed to set_mem_map\n");
|
|
mutex_unlock(&s->ops_mutex);
|
|
mutex_unlock(&s->ops_mutex);
|
|
@@ -371,19 +373,22 @@ out:
|
|
} /* pcmcia_release_io */
|
|
} /* pcmcia_release_io */
|
|
|
|
|
|
|
|
|
|
-int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh)
|
|
|
|
|
|
+int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
|
|
{
|
|
{
|
|
struct pcmcia_socket *s = p_dev->socket;
|
|
struct pcmcia_socket *s = p_dev->socket;
|
|
pccard_mem_map *win;
|
|
pccard_mem_map *win;
|
|
|
|
+ unsigned int w;
|
|
|
|
|
|
- wh--;
|
|
|
|
- if (wh >= MAX_WIN)
|
|
|
|
|
|
+ dev_dbg(&p_dev->dev, "releasing window %pR\n", res);
|
|
|
|
+
|
|
|
|
+ w = ((res->flags & IORESOURCE_BITS & WIN_FLAGS_REQ) >> 2) - 1;
|
|
|
|
+ if (w >= MAX_WIN)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
mutex_lock(&s->ops_mutex);
|
|
mutex_lock(&s->ops_mutex);
|
|
- win = &s->win[wh];
|
|
|
|
|
|
+ win = &s->win[w];
|
|
|
|
|
|
- if (!(p_dev->_win & CLIENT_WIN_REQ(wh))) {
|
|
|
|
|
|
+ if (!(p_dev->_win & CLIENT_WIN_REQ(w))) {
|
|
dev_dbg(&s->dev, "not releasing unknown window\n");
|
|
dev_dbg(&s->dev, "not releasing unknown window\n");
|
|
mutex_unlock(&s->ops_mutex);
|
|
mutex_unlock(&s->ops_mutex);
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -392,7 +397,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh)
|
|
/* Shut down memory window */
|
|
/* Shut down memory window */
|
|
win->flags &= ~MAP_ACTIVE;
|
|
win->flags &= ~MAP_ACTIVE;
|
|
s->ops->set_mem_map(s, win);
|
|
s->ops->set_mem_map(s, win);
|
|
- s->state &= ~SOCKET_WIN_REQ(wh);
|
|
|
|
|
|
+ s->state &= ~SOCKET_WIN_REQ(w);
|
|
|
|
|
|
/* Release system memory */
|
|
/* Release system memory */
|
|
if (win->res) {
|
|
if (win->res) {
|
|
@@ -400,7 +405,7 @@ int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh)
|
|
kfree(win->res);
|
|
kfree(win->res);
|
|
win->res = NULL;
|
|
win->res = NULL;
|
|
}
|
|
}
|
|
- p_dev->_win &= ~CLIENT_WIN_REQ(wh);
|
|
|
|
|
|
+ p_dev->_win &= ~CLIENT_WIN_REQ(w);
|
|
mutex_unlock(&s->ops_mutex);
|
|
mutex_unlock(&s->ops_mutex);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -775,23 +780,18 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
|
struct pcmcia_socket *s = p_dev->socket;
|
|
struct pcmcia_socket *s = p_dev->socket;
|
|
pccard_mem_map *win;
|
|
pccard_mem_map *win;
|
|
u_long align;
|
|
u_long align;
|
|
|
|
+ struct resource *res;
|
|
int w;
|
|
int w;
|
|
|
|
|
|
if (!(s->state & SOCKET_PRESENT)) {
|
|
if (!(s->state & SOCKET_PRESENT)) {
|
|
dev_dbg(&s->dev, "No card present\n");
|
|
dev_dbg(&s->dev, "No card present\n");
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
}
|
|
}
|
|
- if (req->Attributes & (WIN_PAGED | WIN_SHARED)) {
|
|
|
|
- dev_dbg(&s->dev, "bad attribute setting for iomem region\n");
|
|
|
|
- return -EINVAL;
|
|
|
|
- }
|
|
|
|
|
|
|
|
/* Window size defaults to smallest available */
|
|
/* Window size defaults to smallest available */
|
|
if (req->Size == 0)
|
|
if (req->Size == 0)
|
|
req->Size = s->map_size;
|
|
req->Size = s->map_size;
|
|
- align = (((s->features & SS_CAP_MEM_ALIGN) ||
|
|
|
|
- (req->Attributes & WIN_STRICT_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(&s->dev, "invalid map size\n");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -805,20 +805,21 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
|
align = 0;
|
|
align = 0;
|
|
|
|
|
|
/* Allocate system memory window */
|
|
/* Allocate system memory window */
|
|
|
|
+ mutex_lock(&s->ops_mutex);
|
|
for (w = 0; w < MAX_WIN; w++)
|
|
for (w = 0; w < MAX_WIN; w++)
|
|
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(&s->dev, "all windows are used already\n");
|
|
|
|
+ mutex_unlock(&s->ops_mutex);
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
- mutex_lock(&s->ops_mutex);
|
|
|
|
win = &s->win[w];
|
|
win = &s->win[w];
|
|
|
|
|
|
if (!(s->features & SS_CAP_STATIC_MAP)) {
|
|
if (!(s->features & SS_CAP_STATIC_MAP)) {
|
|
win->res = pcmcia_find_mem_region(req->Base, req->Size, align,
|
|
win->res = pcmcia_find_mem_region(req->Base, req->Size, align,
|
|
- (req->Attributes & WIN_MAP_BELOW_1MB), s);
|
|
|
|
|
|
+ 0, s);
|
|
if (!win->res) {
|
|
if (!win->res) {
|
|
dev_dbg(&s->dev, "allocating mem region failed\n");
|
|
dev_dbg(&s->dev, "allocating mem region failed\n");
|
|
mutex_unlock(&s->ops_mutex);
|
|
mutex_unlock(&s->ops_mutex);
|
|
@@ -829,16 +830,8 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
|
|
|
|
|
/* Configure the socket controller */
|
|
/* Configure the socket controller */
|
|
win->map = w+1;
|
|
win->map = w+1;
|
|
- win->flags = 0;
|
|
|
|
|
|
+ win->flags = req->Attributes;
|
|
win->speed = req->AccessSpeed;
|
|
win->speed = req->AccessSpeed;
|
|
- if (req->Attributes & WIN_MEMORY_TYPE)
|
|
|
|
- win->flags |= MAP_ATTRIB;
|
|
|
|
- if (req->Attributes & WIN_ENABLE)
|
|
|
|
- win->flags |= MAP_ACTIVE;
|
|
|
|
- if (req->Attributes & WIN_DATA_WIDTH_16)
|
|
|
|
- win->flags |= MAP_16BIT;
|
|
|
|
- if (req->Attributes & WIN_USE_WAIT)
|
|
|
|
- win->flags |= MAP_USE_WAIT;
|
|
|
|
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) {
|
|
@@ -854,8 +847,16 @@ int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_ha
|
|
else
|
|
else
|
|
req->Base = win->res->start;
|
|
req->Base = win->res->start;
|
|
|
|
|
|
|
|
+ /* convert to new-style resources */
|
|
|
|
+ res = p_dev->resource[w + MAX_IO_WIN];
|
|
|
|
+ res->start = req->Base;
|
|
|
|
+ res->end = req->Base + req->Size - 1;
|
|
|
|
+ res->flags &= ~IORESOURCE_BITS;
|
|
|
|
+ res->flags |= (req->Attributes & WIN_FLAGS_MAP) | (win->map << 2);
|
|
|
|
+ dev_dbg(&s->dev, "request_window results in %pR\n", res);
|
|
|
|
+
|
|
mutex_unlock(&s->ops_mutex);
|
|
mutex_unlock(&s->ops_mutex);
|
|
- *wh = w + 1;
|
|
|
|
|
|
+ *wh = res;
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
} /* pcmcia_request_window */
|
|
} /* pcmcia_request_window */
|
|
@@ -863,13 +864,18 @@ EXPORT_SYMBOL(pcmcia_request_window);
|
|
|
|
|
|
void pcmcia_disable_device(struct pcmcia_device *p_dev)
|
|
void pcmcia_disable_device(struct pcmcia_device *p_dev)
|
|
{
|
|
{
|
|
|
|
+ int i;
|
|
|
|
+ for (i = 0; i < MAX_WIN; i++) {
|
|
|
|
+ struct resource *res = p_dev->resource[MAX_IO_WIN + i];
|
|
|
|
+ if (res->flags & WIN_FLAGS_REQ)
|
|
|
|
+ pcmcia_release_window(p_dev, res);
|
|
|
|
+ }
|
|
|
|
+
|
|
pcmcia_release_configuration(p_dev);
|
|
pcmcia_release_configuration(p_dev);
|
|
pcmcia_release_io(p_dev);
|
|
pcmcia_release_io(p_dev);
|
|
if (p_dev->_irq) {
|
|
if (p_dev->_irq) {
|
|
free_irq(p_dev->irq, p_dev->priv);
|
|
free_irq(p_dev->irq, p_dev->priv);
|
|
p_dev->_irq = 0;
|
|
p_dev->_irq = 0;
|
|
}
|
|
}
|
|
- if (p_dev->win)
|
|
|
|
- pcmcia_release_window(p_dev, p_dev->win);
|
|
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(pcmcia_disable_device);
|
|
EXPORT_SYMBOL(pcmcia_disable_device);
|