Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
5716d415
Commit
5716d415
authored
Jul 11, 2010
by
Dominik Brodowski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
pcmcia: remove obsolete ioctl
Signed-off-by:
Dominik Brodowski
<
linux@dominikbrodowski.net
>
parent
b37fa16e
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
7 additions
and
1383 deletions
+7
-1383
Documentation/feature-removal-schedule.txt
Documentation/feature-removal-schedule.txt
+0
-23
drivers/pcmcia/Makefile
drivers/pcmcia/Makefile
+0
-1
drivers/pcmcia/cs_internal.h
drivers/pcmcia/cs_internal.h
+2
-38
drivers/pcmcia/ds.c
drivers/pcmcia/ds.c
+4
-22
drivers/pcmcia/pcmcia_ioctl.c
drivers/pcmcia/pcmcia_ioctl.c
+0
-1077
drivers/pcmcia/rsrc_iodyn.c
drivers/pcmcia/rsrc_iodyn.c
+0
-2
drivers/pcmcia/rsrc_mgr.c
drivers/pcmcia/rsrc_mgr.c
+0
-2
drivers/pcmcia/rsrc_nonstatic.c
drivers/pcmcia/rsrc_nonstatic.c
+0
-2
include/pcmcia/ds.h
include/pcmcia/ds.h
+0
-209
include/pcmcia/ss.h
include/pcmcia/ss.h
+1
-7
No files found.
Documentation/feature-removal-schedule.txt
View file @
5716d415
...
...
@@ -116,29 +116,6 @@ Who: Mauro Carvalho Chehab <mchehab@infradead.org>
---------------------------
What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl])
When: 2.6.35/2.6.36
Files: drivers/pcmcia/: pcmcia_ioctl.c
Why: With the 16-bit PCMCIA subsystem now behaving (almost) like a
normal hotpluggable bus, and with it using the default kernel
infrastructure (hotplug, driver core, sysfs) keeping the PCMCIA
control ioctl needed by cardmgr and cardctl from pcmcia-cs is
unnecessary and potentially harmful (it does not provide for
proper locking), and makes further cleanups and integration of the
PCMCIA subsystem into the Linux kernel device driver model more
difficult. The features provided by cardmgr and cardctl are either
handled by the kernel itself now or are available in the new
pcmciautils package available at
http://kernel.org/pub/linux/utils/kernel/pcmcia/
For all architectures except ARM, the associated config symbol
has been removed from kernel 2.6.34; for ARM, it will be likely
be removed from kernel 2.6.35. The actual code will then likely
be removed from kernel 2.6.36.
Who: Dominik Brodowski <linux@dominikbrodowski.net>
---------------------------
What: sys_sysctl
When: September 2010
Option: CONFIG_SYSCTL_SYSCALL
...
...
drivers/pcmcia/Makefile
View file @
5716d415
...
...
@@ -7,7 +7,6 @@ pcmcia_core-$(CONFIG_CARDBUS) += cardbus.o
obj-$(CONFIG_PCCARD)
+=
pcmcia_core.o
pcmcia-y
+=
ds.o pcmcia_resource.o cistpl.o pcmcia_cis.o
pcmcia-$(CONFIG_PCMCIA_IOCTL)
+=
pcmcia_ioctl.o
obj-$(CONFIG_PCMCIA)
+=
pcmcia.o
pcmcia_rsrc-y
+=
rsrc_mgr.o
...
...
drivers/pcmcia/cs_internal.h
View file @
5716d415
...
...
@@ -60,14 +60,6 @@ struct pccard_resource_ops {
struct
resource
*
(
*
find_mem
)
(
unsigned
long
base
,
unsigned
long
num
,
unsigned
long
align
,
int
low
,
struct
pcmcia_socket
*
s
);
int
(
*
add_io
)
(
struct
pcmcia_socket
*
s
,
unsigned
int
action
,
unsigned
long
r_start
,
unsigned
long
r_end
);
int
(
*
add_mem
)
(
struct
pcmcia_socket
*
s
,
unsigned
int
action
,
unsigned
long
r_start
,
unsigned
long
r_end
);
int
(
*
init
)
(
struct
pcmcia_socket
*
s
);
void
(
*
exit
)
(
struct
pcmcia_socket
*
s
);
};
...
...
@@ -146,6 +138,8 @@ void pcmcia_put_socket(struct pcmcia_socket *skt);
/* ds.c */
extern
struct
bus_type
pcmcia_bus_type
;
struct
pcmcia_device
;
/* pcmcia_resource.c */
extern
int
pcmcia_release_configuration
(
struct
pcmcia_device
*
p_dev
);
extern
int
pcmcia_validate_mem
(
struct
pcmcia_socket
*
s
);
...
...
@@ -188,34 +182,4 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function,
int
pccard_get_tuple_data
(
struct
pcmcia_socket
*
s
,
tuple_t
*
tuple
);
#ifdef CONFIG_PCMCIA_IOCTL
/* ds.c */
extern
struct
pcmcia_device
*
pcmcia_get_dev
(
struct
pcmcia_device
*
p_dev
);
extern
void
pcmcia_put_dev
(
struct
pcmcia_device
*
p_dev
);
struct
pcmcia_device
*
pcmcia_device_add
(
struct
pcmcia_socket
*
s
,
unsigned
int
function
);
/* pcmcia_ioctl.c */
extern
void
__init
pcmcia_setup_ioctl
(
void
);
extern
void
__exit
pcmcia_cleanup_ioctl
(
void
);
extern
void
handle_event
(
struct
pcmcia_socket
*
s
,
event_t
event
);
extern
int
handle_request
(
struct
pcmcia_socket
*
s
,
event_t
event
);
#else
/* CONFIG_PCMCIA_IOCTL */
static
inline
void
__init
pcmcia_setup_ioctl
(
void
)
{
return
;
}
static
inline
void
__exit
pcmcia_cleanup_ioctl
(
void
)
{
return
;
}
static
inline
void
handle_event
(
struct
pcmcia_socket
*
s
,
event_t
event
)
{
return
;
}
static
inline
int
handle_request
(
struct
pcmcia_socket
*
s
,
event_t
event
)
{
return
0
;
}
#endif
/* CONFIG_PCMCIA_IOCTL */
#endif
/* _LINUX_CS_INTERNAL_H */
drivers/pcmcia/ds.c
View file @
5716d415
...
...
@@ -213,7 +213,7 @@ EXPORT_SYMBOL(pcmcia_unregister_driver);
/* pcmcia_device handling */
struct
pcmcia_device
*
pcmcia_get_dev
(
struct
pcmcia_device
*
p_dev
)
st
atic
st
ruct
pcmcia_device
*
pcmcia_get_dev
(
struct
pcmcia_device
*
p_dev
)
{
struct
device
*
tmp_dev
;
tmp_dev
=
get_device
(
&
p_dev
->
dev
);
...
...
@@ -222,7 +222,7 @@ struct pcmcia_device *pcmcia_get_dev(struct pcmcia_device *p_dev)
return
to_pcmcia_dev
(
tmp_dev
);
}
void
pcmcia_put_dev
(
struct
pcmcia_device
*
p_dev
)
static
void
pcmcia_put_dev
(
struct
pcmcia_device
*
p_dev
)
{
if
(
p_dev
)
put_device
(
&
p_dev
->
dev
);
...
...
@@ -477,7 +477,8 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
}
struct
pcmcia_device
*
pcmcia_device_add
(
struct
pcmcia_socket
*
s
,
unsigned
int
function
)
static
struct
pcmcia_device
*
pcmcia_device_add
(
struct
pcmcia_socket
*
s
,
unsigned
int
function
)
{
struct
pcmcia_device
*
p_dev
,
*
tmp_dev
;
int
i
;
...
...
@@ -885,14 +886,6 @@ static int pcmcia_bus_match(struct device *dev, struct device_driver *drv)
}
mutex_unlock
(
&
p_drv
->
dynids
.
lock
);
#ifdef CONFIG_PCMCIA_IOCTL
/* matching by cardmgr */
if
(
p_dev
->
cardmgr
==
p_drv
)
{
dev_dbg
(
dev
,
"cardmgr matched to %s
\n
"
,
drv
->
name
);
return
1
;
}
#endif
while
(
did
&&
did
->
match_flags
)
{
dev_dbg
(
dev
,
"trying to match to %s
\n
"
,
drv
->
name
);
if
(
pcmcia_devmatch
(
p_dev
,
did
))
{
...
...
@@ -1245,7 +1238,6 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
case
CS_EVENT_CARD_REMOVAL
:
atomic_set
(
&
skt
->
present
,
0
);
pcmcia_card_remove
(
skt
,
NULL
);
handle_event
(
skt
,
event
);
mutex_lock
(
&
s
->
ops_mutex
);
destroy_cis_cache
(
s
);
pcmcia_cleanup_irq
(
s
);
...
...
@@ -1259,7 +1251,6 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
destroy_cis_cache
(
s
);
/* to be on the safe side... */
mutex_unlock
(
&
s
->
ops_mutex
);
pcmcia_card_add
(
skt
);
handle_event
(
skt
,
event
);
break
;
case
CS_EVENT_EJECTION_REQUEST
:
...
...
@@ -1280,14 +1271,12 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
ds_event
(
skt
,
CS_EVENT_CARD_INSERTION
,
CS_EVENT_PRI_LOW
);
}
handle_event
(
skt
,
event
);
break
;
case
CS_EVENT_PM_SUSPEND
:
case
CS_EVENT_RESET_PHYSICAL
:
case
CS_EVENT_CARD_RESET
:
default:
handle_event
(
skt
,
event
);
break
;
}
...
...
@@ -1350,9 +1339,6 @@ static int __devinit pcmcia_bus_add_socket(struct device *dev,
return
ret
;
}
#ifdef CONFIG_PCMCIA_IOCTL
init_waitqueue_head
(
&
socket
->
queue
);
#endif
INIT_LIST_HEAD
(
&
socket
->
devices_list
);
memset
(
&
socket
->
pcmcia_state
,
0
,
sizeof
(
u8
));
socket
->
device_count
=
0
;
...
...
@@ -1429,8 +1415,6 @@ static int __init init_pcmcia_bus(void)
return
ret
;
}
pcmcia_setup_ioctl
();
return
0
;
}
fs_initcall
(
init_pcmcia_bus
);
/* one level after subsys_initcall so that
...
...
@@ -1439,8 +1423,6 @@ fs_initcall(init_pcmcia_bus); /* one level after subsys_initcall so that
static
void
__exit
exit_pcmcia_bus
(
void
)
{
pcmcia_cleanup_ioctl
();
class_interface_unregister
(
&
pcmcia_bus_interface
);
bus_unregister
(
&
pcmcia_bus_type
);
...
...
drivers/pcmcia/pcmcia_ioctl.c
deleted
100644 → 0
View file @
b37fa16e
/*
* pcmcia_ioctl.c -- ioctl interface for cardmgr and cardctl
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* (C) 1999 David A. Hinds
* (C) 2003 - 2004 Dominik Brodowski
*/
/*
* This file will go away soon.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/major.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/proc_fs.h>
#include <linux/poll.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
#include <linux/smp_lock.h>
#include <linux/workqueue.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
#include <pcmcia/ss.h>
#include "cs_internal.h"
static
int
major_dev
=
-
1
;
/* Device user information */
#define MAX_EVENTS 32
#define USER_MAGIC 0x7ea4
#define CHECK_USER(u) \
(((u) == NULL) || ((u)->user_magic != USER_MAGIC))
typedef
struct
user_info_t
{
u_int
user_magic
;
int
event_head
,
event_tail
;
event_t
event
[
MAX_EVENTS
];
struct
user_info_t
*
next
;
struct
pcmcia_socket
*
socket
;
}
user_info_t
;
static
struct
pcmcia_device
*
get_pcmcia_device
(
struct
pcmcia_socket
*
s
,
unsigned
int
function
)
{
struct
pcmcia_device
*
p_dev
=
NULL
;
mutex_lock
(
&
s
->
ops_mutex
);
list_for_each_entry
(
p_dev
,
&
s
->
devices_list
,
socket_device_list
)
{
if
(
p_dev
->
func
==
function
)
{
mutex_unlock
(
&
s
->
ops_mutex
);
return
pcmcia_get_dev
(
p_dev
);
}
}
mutex_unlock
(
&
s
->
ops_mutex
);
return
NULL
;
}
/* backwards-compatible accessing of driver --- by name! */
static
struct
pcmcia_driver
*
get_pcmcia_driver
(
dev_info_t
*
dev_info
)
{
struct
device_driver
*
drv
;
struct
pcmcia_driver
*
p_drv
;
drv
=
driver_find
((
char
*
)
dev_info
,
&
pcmcia_bus_type
);
if
(
!
drv
)
return
NULL
;
p_drv
=
container_of
(
drv
,
struct
pcmcia_driver
,
drv
);
return
p_drv
;
}
#ifdef CONFIG_PROC_FS
static
struct
proc_dir_entry
*
proc_pccard
;
static
int
proc_read_drivers_callback
(
struct
device_driver
*
driver
,
void
*
_m
)
{
struct
seq_file
*
m
=
_m
;
struct
pcmcia_driver
*
p_drv
=
container_of
(
driver
,
struct
pcmcia_driver
,
drv
);
seq_printf
(
m
,
"%-24.24s 1 %d
\n
"
,
p_drv
->
drv
.
name
,
#ifdef CONFIG_MODULE_UNLOAD
(
p_drv
->
owner
)
?
module_refcount
(
p_drv
->
owner
)
:
1
#else
1
#endif
);
return
0
;
}
static
int
pccard_drivers_proc_show
(
struct
seq_file
*
m
,
void
*
v
)
{
return
bus_for_each_drv
(
&
pcmcia_bus_type
,
NULL
,
m
,
proc_read_drivers_callback
);
}
static
int
pccard_drivers_proc_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
return
single_open
(
file
,
pccard_drivers_proc_show
,
NULL
);
}
static
const
struct
file_operations
pccard_drivers_proc_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
pccard_drivers_proc_open
,
.
read
=
seq_read
,
.
llseek
=
seq_lseek
,
.
release
=
single_release
,
};
#endif
#ifdef CONFIG_PCMCIA_PROBE
static
int
adjust_irq
(
struct
pcmcia_socket
*
s
,
adjust_t
*
adj
)
{
int
irq
;
u32
mask
;
irq
=
adj
->
resource
.
irq
.
IRQ
;
if
((
irq
<
0
)
||
(
irq
>
15
))
return
-
EINVAL
;
if
(
adj
->
Action
!=
REMOVE_MANAGED_RESOURCE
)
return
0
;
mask
=
1
<<
irq
;
if
(
!
(
s
->
irq_mask
&
mask
))
return
0
;
s
->
irq_mask
&=
~
mask
;
return
0
;
}
#else
static
inline
int
adjust_irq
(
struct
pcmcia_socket
*
s
,
adjust_t
*
adj
)
{
return
0
;
}
#endif
static
int
pcmcia_adjust_resource_info
(
adjust_t
*
adj
)
{
struct
pcmcia_socket
*
s
;
int
ret
=
-
ENOSYS
;
down_read
(
&
pcmcia_socket_list_rwsem
);
list_for_each_entry
(
s
,
&
pcmcia_socket_list
,
socket_list
)
{
if
(
adj
->
Resource
==
RES_IRQ
)
ret
=
adjust_irq
(
s
,
adj
);
else
if
(
s
->
resource_ops
->
add_io
)
{
unsigned
long
begin
,
end
;
/* you can't use the old interface if the new
* one was used before */
mutex_lock
(
&
s
->
ops_mutex
);
if
((
s
->
resource_setup_new
)
&&
!
(
s
->
resource_setup_old
))
{
mutex_unlock
(
&
s
->
ops_mutex
);
continue
;
}
else
if
(
!
(
s
->
resource_setup_old
))
s
->
resource_setup_old
=
1
;
switch
(
adj
->
Resource
)
{
case
RES_MEMORY_RANGE
:
begin
=
adj
->
resource
.
memory
.
Base
;
end
=
adj
->
resource
.
memory
.
Base
+
adj
->
resource
.
memory
.
Size
-
1
;
if
(
s
->
resource_ops
->
add_mem
)
ret
=
s
->
resource_ops
->
add_mem
(
s
,
adj
->
Action
,
begin
,
end
);
case
RES_IO_RANGE
:
begin
=
adj
->
resource
.
io
.
BasePort
;
end
=
adj
->
resource
.
io
.
BasePort
+
adj
->
resource
.
io
.
NumPorts
-
1
;
if
(
s
->
resource_ops
->
add_io
)
ret
=
s
->
resource_ops
->
add_io
(
s
,
adj
->
Action
,
begin
,
end
);
}
if
(
!
ret
)
{
/* as there's no way we know this is the
* last call to adjust_resource_info, we
* always need to assume this is the latest
* one... */
s
->
resource_setup_done
=
1
;
}
mutex_unlock
(
&
s
->
ops_mutex
);
}
}
up_read
(
&
pcmcia_socket_list_rwsem
);
return
ret
;
}
/** pcmcia_get_window
*/
static
int
pcmcia_get_window
(
struct
pcmcia_socket
*
s
,
window_handle_t
*
wh_out
,
window_handle_t
wh
,
win_req_t
*
req
)
{
pccard_mem_map
*
win
;
window_handle_t
w
;
wh
--
;
if
(
!
s
||
!
(
s
->
state
&
SOCKET_PRESENT
))
return
-
ENODEV
;
if
(
wh
>=
MAX_WIN
)
return
-
EINVAL
;
for
(
w
=
wh
;
w
<
MAX_WIN
;
w
++
)
if
(
s
->
state
&
SOCKET_WIN_REQ
(
w
))
break
;
if
(
w
==
MAX_WIN
)
return
-
EINVAL
;
win
=
&
s
->
win
[
w
];
req
->
Base
=
win
->
res
->
start
;
req
->
Size
=
win
->
res
->
end
-
win
->
res
->
start
+
1
;
req
->
AccessSpeed
=
win
->
speed
;
req
->
Attributes
=
0
;
if
(
win
->
flags
&
MAP_ATTRIB
)
req
->
Attributes
|=
WIN_MEMORY_TYPE_AM
;
if
(
win
->
flags
&
MAP_ACTIVE
)
req
->
Attributes
|=
WIN_ENABLE
;
if
(
win
->
flags
&
MAP_16BIT
)
req
->
Attributes
|=
WIN_DATA_WIDTH_16
;
if
(
win
->
flags
&
MAP_USE_WAIT
)
req
->
Attributes
|=
WIN_USE_WAIT
;
*
wh_out
=
w
+
1
;
return
0
;
}
/* pcmcia_get_window */
/** pcmcia_get_mem_page
*
* Change the card address of an already open memory window.
*/
static
int
pcmcia_get_mem_page
(
struct
pcmcia_socket
*
skt
,
window_handle_t
wh
,
memreq_t
*
req
)
{
wh
--
;
if
(
wh
>=
MAX_WIN
)
return
-
EINVAL
;
req
->
Page
=
0
;
req
->
CardOffset
=
skt
->
win
[
wh
].
card_start
;
return
0
;
}
/* pcmcia_get_mem_page */
/** pccard_get_status
*
* Get the current socket state bits. We don't support the latched
* SocketState yet: I haven't seen any point for it.
*/
static
int
pccard_get_status
(
struct
pcmcia_socket
*
s
,
struct
pcmcia_device
*
p_dev
,
cs_status_t
*
status
)
{
config_t
*
c
;
int
val
;
s
->
ops
->
get_status
(
s
,
&
val
);
status
->
CardState
=
status
->
SocketState
=
0
;
status
->
CardState
|=
(
val
&
SS_DETECT
)
?
CS_EVENT_CARD_DETECT
:
0
;
status
->
CardState
|=
(
val
&
SS_CARDBUS
)
?
CS_EVENT_CB_DETECT
:
0
;
status
->
CardState
|=
(
val
&
SS_3VCARD
)
?
CS_EVENT_3VCARD
:
0
;
status
->
CardState
|=
(
val
&
SS_XVCARD
)
?
CS_EVENT_XVCARD
:
0
;
if
(
s
->
state
&
SOCKET_SUSPEND
)
status
->
CardState
|=
CS_EVENT_PM_SUSPEND
;
if
(
!
(
s
->
state
&
SOCKET_PRESENT
))
return
-
ENODEV
;
c
=
(
p_dev
)
?
p_dev
->
function_config
:
NULL
;
if
((
c
!=
NULL
)
&&
(
c
->
state
&
CONFIG_LOCKED
)
&&
(
c
->
IntType
&
(
INT_MEMORY_AND_IO
|
INT_ZOOMED_VIDEO
)))
{
u_char
reg
;
if
(
c
->
CardValues
&
PRESENT_PIN_REPLACE
)
{
mutex_lock
(
&
s
->
ops_mutex
);
pcmcia_read_cis_mem
(
s
,
1
,
(
c
->
ConfigBase
+
CISREG_PRR
)
>>
1
,
1
,
&
reg
);
mutex_unlock
(
&
s
->
ops_mutex
);
status
->
CardState
|=
(
reg
&
PRR_WP_STATUS
)
?
CS_EVENT_WRITE_PROTECT
:
0
;
status
->
CardState
|=
(
reg
&
PRR_READY_STATUS
)
?
CS_EVENT_READY_CHANGE
:
0
;
status
->
CardState
|=
(
reg
&
PRR_BVD2_STATUS
)
?
CS_EVENT_BATTERY_LOW
:
0
;
status
->
CardState
|=
(
reg
&
PRR_BVD1_STATUS
)
?
CS_EVENT_BATTERY_DEAD
:
0
;
}
else
{
/* No PRR? Then assume we're always ready */
status
->
CardState
|=
CS_EVENT_READY_CHANGE
;
}
if
(
c
->
CardValues
&
PRESENT_EXT_STATUS
)
{
mutex_lock
(
&
s
->
ops_mutex
);
pcmcia_read_cis_mem
(
s
,
1
,
(
c
->
ConfigBase
+
CISREG_ESR
)
>>
1
,
1
,
&
reg
);
mutex_unlock
(
&
s
->
ops_mutex
);
status
->
CardState
|=
(
reg
&
ESR_REQ_ATTN
)
?
CS_EVENT_REQUEST_ATTENTION
:
0
;
}
return
0
;
}
status
->
CardState
|=
(
val
&
SS_WRPROT
)
?
CS_EVENT_WRITE_PROTECT
:
0
;
status
->
CardState
|=
(
val
&
SS_BATDEAD
)
?
CS_EVENT_BATTERY_DEAD
:
0
;
status
->
CardState
|=
(
val
&
SS_BATWARN
)
?
CS_EVENT_BATTERY_LOW
:
0
;
status
->
CardState
|=
(
val
&
SS_READY
)
?
CS_EVENT_READY_CHANGE
:
0
;
return
0
;
}
/* pccard_get_status */
static
int
pccard_get_configuration_info
(
struct
pcmcia_socket
*
s
,
struct
pcmcia_device
*
p_dev
,
config_info_t
*
config
)
{
config_t
*
c
;
if
(
!
(
s
->
state
&
SOCKET_PRESENT
))
return
-
ENODEV
;
#ifdef CONFIG_CARDBUS
if
(
s
->
state
&
SOCKET_CARDBUS
)
{
memset
(
config
,
0
,
sizeof
(
config_info_t
));
config
->
Vcc
=
s
->
socket
.
Vcc
;
config
->
Vpp1
=
config
->
Vpp2
=
s
->
socket
.
Vpp
;
config
->
Option
=
s
->
cb_dev
->
subordinate
->
number
;
if
(
s
->
state
&
SOCKET_CARDBUS_CONFIG
)
{
config
->
Attributes
=
CONF_VALID_CLIENT
;
config
->
IntType
=
INT_CARDBUS
;
config
->
AssignedIRQ
=
s
->
pcmcia_irq
;
if
(
config
->
AssignedIRQ
)
config
->
Attributes
|=
CONF_ENABLE_IRQ
;
if
(
s
->
io
[
0
].
res
)
{
config
->
BasePort1
=
s
->
io
[
0
].
res
->
start
;
config
->
NumPorts1
=
s
->
io
[
0
].
res
->
end
-
config
->
BasePort1
+
1
;
}
}
return
0
;
}
#endif
if
(
p_dev
)
{
c
=
p_dev
->
function_config
;
config
->
Function
=
p_dev
->
func
;
}
else
{
c
=
NULL
;
config
->
Function
=
0
;
}
if
((
c
==
NULL
)
||
!
(
c
->
state
&
CONFIG_LOCKED
))
{
config
->
Attributes
=
0
;
config
->
Vcc
=
s
->
socket
.
Vcc
;
config
->
Vpp1
=
config
->
Vpp2
=
s
->
socket
.
Vpp
;
return
0
;
}
config
->
Attributes
=
c
->
Attributes
|
CONF_VALID_CLIENT
;
config
->
Vcc
=
s
->
socket
.
Vcc
;
config
->
Vpp1
=
config
->
Vpp2
=
s
->
socket
.
Vpp
;
config
->
IntType
=
c
->
IntType
;
config
->
ConfigBase
=
c
->
ConfigBase
;
config
->
Status
=
c
->
Status
;
config
->
Pin
=
c
->
Pin
;
config
->
Copy
=
c
->
Copy
;
config
->
Option
=
c
->
Option
;
config
->
ExtStatus
=
c
->
ExtStatus
;
config
->
Present
=
config
->
CardValues
=
c
->
CardValues
;
config
->
IRQAttributes
=
c
->
irq
.
Attributes
;
config
->
AssignedIRQ
=
s
->
pcmcia_irq
;
config
->
BasePort1
=
c
->
io
.
BasePort1
;
config
->
NumPorts1
=
c
->
io
.
NumPorts1
;
config
->
Attributes1
=
c
->
io
.
Attributes1
;
config
->
BasePort2
=
c
->
io
.
BasePort2
;
config
->
NumPorts2
=
c
->
io
.
NumPorts2
;
config
->
Attributes2
=
c
->
io
.
Attributes2
;
config
->
IOAddrLines
=
c
->
io
.
IOAddrLines
;
return
0
;
}
/* pccard_get_configuration_info */
/*======================================================================
These manage a ring buffer of events pending for one user process
======================================================================*/
static
int
queue_empty
(
user_info_t
*
user
)
{
return
(
user
->
event_head
==
user
->
event_tail
);
}
static
event_t
get_queued_event
(
user_info_t
*
user
)
{
user
->
event_tail
=
(
user
->
event_tail
+
1
)
%
MAX_EVENTS
;
return
user
->
event
[
user
->
event_tail
];
}
static
void
queue_event
(
user_info_t
*
user
,
event_t
event
)
{
user
->
event_head
=
(
user
->
event_head
+
1
)
%
MAX_EVENTS
;
if
(
user
->
event_head
==
user
->
event_tail
)
user
->
event_tail
=
(
user
->
event_tail
+
1
)
%
MAX_EVENTS
;
user
->
event
[
user
->
event_head
]
=
event
;
}
void
handle_event
(
struct
pcmcia_socket
*
s
,
event_t
event
)
{
user_info_t
*
user
;
for
(
user
=
s
->
user
;
user
;
user
=
user
->
next
)
queue_event
(
user
,
event
);
wake_up_interruptible
(
&
s
->
queue
);
}
/*======================================================================
bind_request() and bind_device() are merged by now. Register_client()
is called right at the end of bind_request(), during the driver's
->attach() call. Individual descriptions:
bind_request() connects a socket to a particular client driver.
It looks up the specified device ID in the list of registered
drivers, binds it to the socket, and tries to create an instance
of the device. unbind_request() deletes a driver instance.
Bind_device() associates a device driver with a particular socket.
It is normally called by Driver Services after it has identified
a newly inserted card. An instance of that driver will then be
eligible to register as a client of this socket.
Register_client() uses the dev_info_t handle to match the
caller with a socket. The driver must have already been bound
to a socket with bind_device() -- in fact, bind_device()
allocates the client structure that will be used.
======================================================================*/
static
int
bind_request
(
struct
pcmcia_socket
*
s
,
bind_info_t
*
bind_info
)
{
struct
pcmcia_driver
*
p_drv
;
struct
pcmcia_device
*
p_dev
;
int
ret
=
0
;
s
=
pcmcia_get_socket
(
s
);
if
(
!
s
)
return
-
EINVAL
;
pr_debug
(
"bind_request(%d, '%s')
\n
"
,
s
->
sock
,
(
char
*
)
bind_info
->
dev_info
);
p_drv
=
get_pcmcia_driver
(
&
bind_info
->
dev_info
);
if
(
!
p_drv
)
{
ret
=
-
EINVAL
;
goto
err_put
;
}
if
(
!
try_module_get
(
p_drv
->
owner
))
{
ret
=
-
EINVAL
;
goto
err_put_driver
;
}
mutex_lock
(
&
s
->
ops_mutex
);
list_for_each_entry
(
p_dev
,
&
s
->
devices_list
,
socket_device_list
)
{
if
(
p_dev
->
func
==
bind_info
->
function
)
{
if
((
p_dev
->
dev
.
driver
==
&
p_drv
->
drv
))
{
if
(
p_dev
->
cardmgr
)
{
/* if there's already a device
* registered, and it was registered
* by userspace before, we need to
* return the "instance". */
mutex_unlock
(
&
s
->
ops_mutex
);
bind_info
->
instance
=
p_dev
;
ret
=
-
EBUSY
;
goto
err_put_module
;
}
else
{
/* the correct driver managed to bind
* itself magically to the correct
* device. */
mutex_unlock
(
&
s
->
ops_mutex
);
p_dev
->
cardmgr
=
p_drv
;
ret
=
0
;
goto
err_put_module
;
}
}
else
if
(
!
p_dev
->
dev
.
driver
)
{
/* there's already a device available where
* no device has been bound to yet. So we don't
* need to register a device! */
mutex_unlock
(
&
s
->
ops_mutex
);
goto
rescan
;
}
}
}
mutex_unlock
(
&
s
->
ops_mutex
);
p_dev
=
pcmcia_device_add
(
s
,
bind_info
->
function
);
if
(
!
p_dev
)
{
ret
=
-
EIO
;
goto
err_put_module
;
}
rescan:
p_dev
->
cardmgr
=
p_drv
;
/* if a driver is already running, we can abort */
if
(
p_dev
->
dev
.
driver
)
goto
err_put_module
;
/*
* Prevent this racing with a card insertion.
*/
mutex_lock
(
&
s
->
skt_mutex
);
ret
=
bus_rescan_devices
(
&
pcmcia_bus_type
);
mutex_unlock
(
&
s
->
skt_mutex
);
if
(
ret
)
goto
err_put_module
;
/* check whether the driver indeed matched. I don't care if this
* is racy or not, because it can only happen on cardmgr access
* paths...
*/
if
(
!
(
p_dev
->
dev
.
driver
==
&
p_drv
->
drv
))
p_dev
->
cardmgr
=
NULL
;
err_put_module:
module_put
(
p_drv
->
owner
);
err_put_driver:
put_driver
(
&
p_drv
->
drv
);
err_put:
pcmcia_put_socket
(
s
);
return
ret
;
}
/* bind_request */
#ifdef CONFIG_CARDBUS
static
struct
pci_bus
*
pcmcia_lookup_bus
(
struct
pcmcia_socket
*
s
)
{
if
(
!
s
||
!
(
s
->
state
&
SOCKET_CARDBUS
))
return
NULL
;
return
s
->
cb_dev
->
subordinate
;
}
#endif
static
int
get_device_info
(
struct
pcmcia_socket
*
s
,
bind_info_t
*
bind_info
,
int
first
)
{
struct
pcmcia_device
*
p_dev
;
struct
pcmcia_driver
*
p_drv
;
int
ret
=
0
;
#ifdef CONFIG_CARDBUS
/*
* Some unbelievably ugly code to associate the PCI cardbus
* device and its driver with the PCMCIA "bind" information.
*/
{
struct
pci_bus
*
bus
;
bus
=
pcmcia_lookup_bus
(
s
);
if
(
bus
)
{
struct
list_head
*
list
;
struct
pci_dev
*
dev
=
NULL
;
list
=
bus
->
devices
.
next
;
while
(
list
!=
&
bus
->
devices
)
{
struct
pci_dev
*
pdev
=
pci_dev_b
(
list
);
list
=
list
->
next
;
if
(
first
)
{
dev
=
pdev
;
break
;
}
/* Try to handle "next" here some way? */
}
if
(
dev
&&
dev
->
driver
)
{
strlcpy
(
bind_info
->
name
,
dev
->
driver
->
name
,
DEV_NAME_LEN
);
bind_info
->
major
=
0
;
bind_info
->
minor
=
0
;
bind_info
->
next
=
NULL
;
return
0
;
}
}
}
#endif
mutex_lock
(
&
s
->
ops_mutex
);
list_for_each_entry
(
p_dev
,
&
s
->
devices_list
,
socket_device_list
)
{
if
(
p_dev
->
func
==
bind_info
->
function
)
{
p_dev
=
pcmcia_get_dev
(
p_dev
);
if
(
!
p_dev
)
continue
;
goto
found
;
}
}
mutex_unlock
(
&
s
->
ops_mutex
);
return
-
ENODEV
;
found:
mutex_unlock
(
&
s
->
ops_mutex
);
p_drv
=
to_pcmcia_drv
(
p_dev
->
dev
.
driver
);
if
(
p_drv
&&
!
p_dev
->
_locked
)
{
ret
=
-
EAGAIN
;
goto
err_put
;
}
if
(
!
first
)
{
ret
=
-
ENODEV
;
goto
err_put
;
}
strlcpy
(
bind_info
->
name
,
dev_name
(
&
p_dev
->
dev
),
DEV_NAME_LEN
);
bind_info
->
next
=
NULL
;
err_put:
pcmcia_put_dev
(
p_dev
);
return
ret
;
}
/* get_device_info */
static
int
ds_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
socket_t
i
=
iminor
(
inode
);
struct
pcmcia_socket
*
s
;
user_info_t
*
user
;
static
int
warning_printed
;
int
ret
=
0
;
pr_debug
(
"ds_open(socket %d)
\n
"
,
i
);
lock_kernel
();
s
=
pcmcia_get_socket_by_nr
(
i
);
if
(
!
s
)
{
ret
=
-
ENODEV
;
goto
out
;
}
s
=
pcmcia_get_socket
(
s
);
if
(
!
s
)
{
ret
=
-
ENODEV
;
goto
out
;
}
if
((
file
->
f_flags
&
O_ACCMODE
)
!=
O_RDONLY
)
{
if
(
s
->
pcmcia_state
.
busy
)
{
pcmcia_put_socket
(
s
);
ret
=
-
EBUSY
;
goto
out
;
}
else
s
->
pcmcia_state
.
busy
=
1
;
}
user
=
kmalloc
(
sizeof
(
user_info_t
),
GFP_KERNEL
);
if
(
!
user
)
{
pcmcia_put_socket
(
s
);
ret
=
-
ENOMEM
;
goto
out
;
}
user
->
event_tail
=
user
->
event_head
=
0
;
user
->
next
=
s
->
user
;
user
->
user_magic
=
USER_MAGIC
;
user
->
socket
=
s
;
s
->
user
=
user
;
file
->
private_data
=
user
;
if
(
!
warning_printed
)
{
printk
(
KERN_INFO
"pcmcia: Detected deprecated PCMCIA ioctl "
"usage from process: %s.
\n
"
,
current
->
comm
);
printk
(
KERN_INFO
"pcmcia: This interface will soon be removed from "
"the kernel; please expect breakage unless you upgrade "
"to new tools.
\n
"
);
printk
(
KERN_INFO
"pcmcia: see http://www.kernel.org/pub/linux/"
"utils/kernel/pcmcia/pcmcia.html for details.
\n
"
);
warning_printed
=
1
;
}
if
(
atomic_read
(
&
s
->
present
))
queue_event
(
user
,
CS_EVENT_CARD_INSERTION
);
out:
unlock_kernel
();
return
ret
;
}
/* ds_open */
/*====================================================================*/
static
int
ds_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
pcmcia_socket
*
s
;
user_info_t
*
user
,
**
link
;
pr_debug
(
"ds_release(socket %d)
\n
"
,
iminor
(
inode
));
user
=
file
->
private_data
;
if
(
CHECK_USER
(
user
))
goto
out
;
s
=
user
->
socket
;
/* Unlink user data structure */
if
((
file
->
f_flags
&
O_ACCMODE
)
!=
O_RDONLY
)
s
->
pcmcia_state
.
busy
=
0
;
file
->
private_data
=
NULL
;
for
(
link
=
&
s
->
user
;
*
link
;
link
=
&
(
*
link
)
->
next
)
if
(
*
link
==
user
)
break
;
if
(
link
==
NULL
)
goto
out
;
*
link
=
user
->
next
;
user
->
user_magic
=
0
;
kfree
(
user
);
pcmcia_put_socket
(
s
);
out:
return
0
;
}
/* ds_release */
/*====================================================================*/
static
ssize_t
ds_read
(
struct
file
*
file
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
struct
pcmcia_socket
*
s
;
user_info_t
*
user
;
int
ret
;
pr_debug
(
"ds_read(socket %d)
\n
"
,
iminor
(
file
->
f_path
.
dentry
->
d_inode
));
if
(
count
<
4
)
return
-
EINVAL
;
user
=
file
->
private_data
;
if
(
CHECK_USER
(
user
))
return
-
EIO
;
s
=
user
->
socket
;
ret
=
wait_event_interruptible
(
s
->
queue
,
!
queue_empty
(
user
));
if
(
ret
==
0
)
ret
=
put_user
(
get_queued_event
(
user
),
(
int
__user
*
)
buf
)
?
-
EFAULT
:
4
;
return
ret
;
}
/* ds_read */
/*====================================================================*/
static
ssize_t
ds_write
(
struct
file
*
file
,
const
char
__user
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
pr_debug
(
"ds_write(socket %d)
\n
"
,
iminor
(
file
->
f_path
.
dentry
->
d_inode
));
if
(
count
!=
4
)
return
-
EINVAL
;
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_RDONLY
)
return
-
EBADF
;
return
-
EIO
;
}
/* ds_write */
/*====================================================================*/
/* No kernel lock - fine */
static
u_int
ds_poll
(
struct
file
*
file
,
poll_table
*
wait
)
{
struct
pcmcia_socket
*
s
;
user_info_t
*
user
;
pr_debug
(
"ds_poll(socket %d)
\n
"
,
iminor
(
file
->
f_path
.
dentry
->
d_inode
));
user
=
file
->
private_data
;
if
(
CHECK_USER
(
user
))
return
POLLERR
;
s
=
user
->
socket
;
/*
* We don't check for a dead socket here since that
* will send cardmgr into an endless spin.
*/
poll_wait
(
file
,
&
s
->
queue
,
wait
);
if
(
!
queue_empty
(
user
))
return
POLLIN
|
POLLRDNORM
;
return
0
;
}
/* ds_poll */
/*====================================================================*/
static
int
ds_ioctl
(
struct
file
*
file
,
u_int
cmd
,
u_long
arg
)
{
struct
pcmcia_socket
*
s
;
void
__user
*
uarg
=
(
char
__user
*
)
arg
;
u_int
size
;
int
ret
,
err
;
ds_ioctl_arg_t
*
buf
;
user_info_t
*
user
;
pr_debug
(
"ds_ioctl(socket %d, %#x, %#lx)
\n
"
,
iminor
(
inode
),
cmd
,
arg
);
user
=
file
->
private_data
;
if
(
CHECK_USER
(
user
))
return
-
EIO
;
s
=
user
->
socket
;
size
=
(
cmd
&
IOCSIZE_MASK
)
>>
IOCSIZE_SHIFT
;
if
(
size
>
sizeof
(
ds_ioctl_arg_t
))
return
-
EINVAL
;
/* Permission check */
if
(
!
(
cmd
&
IOC_OUT
)
&&
!
capable
(
CAP_SYS_ADMIN
))
return
-
EPERM
;
if
(
cmd
&
IOC_IN
)
{
if
(
!
access_ok
(
VERIFY_READ
,
uarg
,
size
))
{
pr_debug
(
"ds_ioctl(): verify_read = %d
\n
"
,
-
EFAULT
);
return
-
EFAULT
;
}
}
if
(
cmd
&
IOC_OUT
)
{
if
(
!
access_ok
(
VERIFY_WRITE
,
uarg
,
size
))
{
pr_debug
(
"ds_ioctl(): verify_write = %d
\n
"
,
-
EFAULT
);
return
-
EFAULT
;
}
}
buf
=
kmalloc
(
sizeof
(
ds_ioctl_arg_t
),
GFP_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
err
=
ret
=
0
;
if
(
cmd
&
IOC_IN
)
{
if
(
__copy_from_user
((
char
*
)
buf
,
uarg
,
size
))
{
err
=
-
EFAULT
;
goto
free_out
;
}
}
switch
(
cmd
)
{
case
DS_ADJUST_RESOURCE_INFO
:
ret
=
pcmcia_adjust_resource_info
(
&
buf
->
adjust
);
break
;
case
DS_GET_CONFIGURATION_INFO
:
if
(
buf
->
config
.
Function
&&
(
buf
->
config
.
Function
>=
s
->
functions
))
ret
=
-
EINVAL
;
else
{
struct
pcmcia_device
*
p_dev
=
get_pcmcia_device
(
s
,
buf
->
config
.
Function
);
ret
=
pccard_get_configuration_info
(
s
,
p_dev
,
&
buf
->
config
);
pcmcia_put_dev
(
p_dev
);
}
break
;
case
DS_GET_FIRST_TUPLE
:
mutex_lock
(
&
s
->
skt_mutex
);
pcmcia_validate_mem
(
s
);
mutex_unlock
(
&
s
->
skt_mutex
);
ret
=
pccard_get_first_tuple
(
s
,
BIND_FN_ALL
,
&
buf
->
tuple
);
break
;
case
DS_GET_NEXT_TUPLE
:
ret
=
pccard_get_next_tuple
(
s
,
BIND_FN_ALL
,
&
buf
->
tuple
);
break
;
case
DS_GET_TUPLE_DATA
:
buf
->
tuple
.
TupleData
=
buf
->
tuple_parse
.
data
;
buf
->
tuple
.
TupleDataMax
=
sizeof
(
buf
->
tuple_parse
.
data
);
ret
=
pccard_get_tuple_data
(
s
,
&
buf
->
tuple
);
break
;
case
DS_PARSE_TUPLE
:
buf
->
tuple
.
TupleData
=
buf
->
tuple_parse
.
data
;
ret
=
pcmcia_parse_tuple
(
&
buf
->
tuple
,
&
buf
->
tuple_parse
.
parse
);
break
;
case
DS_RESET_CARD
:
ret
=
pcmcia_reset_card
(
s
);
break
;
case
DS_GET_STATUS
:
if
(
buf
->
status
.
Function
&&
(
buf
->
status
.
Function
>=
s
->
functions
))
ret
=
-
EINVAL
;
else
{
struct
pcmcia_device
*
p_dev
=
get_pcmcia_device
(
s
,
buf
->
status
.
Function
);
ret
=
pccard_get_status
(
s
,
p_dev
,
&
buf
->
status
);
pcmcia_put_dev
(
p_dev
);
}
break
;
case
DS_VALIDATE_CIS
:
mutex_lock
(
&
s
->
skt_mutex
);
pcmcia_validate_mem
(
s
);
mutex_unlock
(
&
s
->
skt_mutex
);
ret
=
pccard_validate_cis
(
s
,
&
buf
->
cisinfo
.
Chains
);
break
;
case
DS_SUSPEND_CARD
:
pcmcia_parse_uevents
(
s
,
PCMCIA_UEVENT_SUSPEND
);
break
;
case
DS_RESUME_CARD
:
pcmcia_parse_uevents
(
s
,
PCMCIA_UEVENT_RESUME
);
break
;
case
DS_EJECT_CARD
:
pcmcia_parse_uevents
(
s
,
PCMCIA_UEVENT_EJECT
);
break
;
case
DS_INSERT_CARD
:
pcmcia_parse_uevents
(
s
,
PCMCIA_UEVENT_INSERT
);
break
;
case
DS_ACCESS_CONFIGURATION_REGISTER
:
if
((
buf
->
conf_reg
.
Action
==
CS_WRITE
)
&&
!
capable
(
CAP_SYS_ADMIN
))
{
err
=
-
EPERM
;
goto
free_out
;
}
ret
=
-
EINVAL
;
if
(
!
(
buf
->
conf_reg
.
Function
&&
(
buf
->
conf_reg
.
Function
>=
s
->
functions
)))
{
struct
pcmcia_device
*
p_dev
=
get_pcmcia_device
(
s
,
buf
->
conf_reg
.
Function
);
if
(
p_dev
)
{
ret
=
pcmcia_access_configuration_register
(
p_dev
,
&
buf
->
conf_reg
);
pcmcia_put_dev
(
p_dev
);
}
}
break
;
case
DS_GET_FIRST_REGION
:
case
DS_GET_NEXT_REGION
:
case
DS_BIND_MTD
:
if
(
!
capable
(
CAP_SYS_ADMIN
))
{
err
=
-
EPERM
;
goto
free_out
;
}
else
{
printk_once
(
KERN_WARNING
"2.6. kernels use pcmciamtd instead of memory_cs.c and do not require special
\n
"
);
printk_once
(
KERN_WARNING
"MTD handling any more.
\n
"
);
}
err
=
-
EINVAL
;
goto
free_out
;
break
;
case
DS_GET_FIRST_WINDOW
:
ret
=
pcmcia_get_window
(
s
,
&
buf
->
win_info
.
handle
,
1
,
&
buf
->
win_info
.
window
);
break
;
case
DS_GET_NEXT_WINDOW
:
ret
=
pcmcia_get_window
(
s
,
&
buf
->
win_info
.
handle
,
buf
->
win_info
.
handle
+
1
,
&
buf
->
win_info
.
window
);
break
;
case
DS_GET_MEM_PAGE
:
ret
=
pcmcia_get_mem_page
(
s
,
buf
->
win_info
.
handle
,
&
buf
->
win_info
.
map
);
break
;
case
DS_REPLACE_CIS
:
ret
=
pcmcia_replace_cis
(
s
,
buf
->
cisdump
.
Data
,
buf
->
cisdump
.
Length
);
break
;
case
DS_BIND_REQUEST
:
if
(
!
capable
(
CAP_SYS_ADMIN
))
{
err
=
-
EPERM
;
goto
free_out
;
}
err
=
bind_request
(
s
,
&
buf
->
bind_info
);
break
;
case
DS_GET_DEVICE_INFO
:
err
=
get_device_info
(
s
,
&
buf
->
bind_info
,
1
);
break
;
case
DS_GET_NEXT_DEVICE
:
err
=
get_device_info
(
s
,
&
buf
->
bind_info
,
0
);
break
;
case
DS_UNBIND_REQUEST
:
err
=
0
;
break
;
default:
err
=
-
EINVAL
;
}
if
((
err
==
0
)
&&
(
ret
!=
0
))
{
pr_debug
(
"ds_ioctl: ret = %d
\n
"
,
ret
);
switch
(
ret
)
{
case
-
ENODEV
:
case
-
EINVAL
:
case
-
EBUSY
:
case
-
ENOSYS
:
err
=
ret
;
break
;
case
-
ENOMEM
:
err
=
-
ENOSPC
;
break
;
case
-
ENOSPC
:
err
=
-
ENODATA
;
break
;
default:
err
=
-
EIO
;
break
;
}
}
if
(
cmd
&
IOC_OUT
)
{
if
(
__copy_to_user
(
uarg
,
(
char
*
)
buf
,
size
))
err
=
-
EFAULT
;
}
free_out:
kfree
(
buf
);
return
err
;
}
/* ds_ioctl */
static
long
ds_unlocked_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
int
ret
;
lock_kernel
();
ret
=
ds_ioctl
(
file
,
cmd
,
arg
);
unlock_kernel
();
return
ret
;
}
/*====================================================================*/
static
const
struct
file_operations
ds_fops
=
{
.
owner
=
THIS_MODULE
,
.
open
=
ds_open
,
.
release
=
ds_release
,
.
unlocked_ioctl
=
ds_unlocked_ioctl
,
.
read
=
ds_read
,
.
write
=
ds_write
,
.
poll
=
ds_poll
,
};
void
__init
pcmcia_setup_ioctl
(
void
)
{
int
i
;
/* Set up character device for user mode clients */
i
=
register_chrdev
(
0
,
"pcmcia"
,
&
ds_fops
);
if
(
i
<
0
)
printk
(
KERN_NOTICE
"unable to find a free device # for "
"Driver Services (error=%d)
\n
"
,
i
);
else
major_dev
=
i
;
#ifdef CONFIG_PROC_FS
proc_pccard
=
proc_mkdir
(
"bus/pccard"
,
NULL
);
if
(
proc_pccard
)
proc_create
(
"drivers"
,
0
,
proc_pccard
,
&
pccard_drivers_proc_fops
);
#endif
}
void
__exit
pcmcia_cleanup_ioctl
(
void
)
{
#ifdef CONFIG_PROC_FS
if
(
proc_pccard
)
{
remove_proc_entry
(
"drivers"
,
proc_pccard
);
remove_proc_entry
(
"bus/pccard"
,
NULL
);
}
#endif
if
(
major_dev
!=
-
1
)
unregister_chrdev
(
major_dev
,
"pcmcia"
);
}
drivers/pcmcia/rsrc_iodyn.c
View file @
5716d415
...
...
@@ -164,8 +164,6 @@ struct pccard_resource_ops pccard_iodyn_ops = {
.
validate_mem
=
NULL
,
.
find_io
=
iodyn_find_io
,
.
find_mem
=
NULL
,
.
add_io
=
NULL
,
.
add_mem
=
NULL
,
.
init
=
static_init
,
.
exit
=
NULL
,
};
...
...
drivers/pcmcia/rsrc_mgr.c
View file @
5716d415
...
...
@@ -62,8 +62,6 @@ struct pccard_resource_ops pccard_static_ops = {
.
validate_mem
=
NULL
,
.
find_io
=
static_find_io
,
.
find_mem
=
NULL
,
.
add_io
=
NULL
,
.
add_mem
=
NULL
,
.
init
=
static_init
,
.
exit
=
NULL
,
};
...
...
drivers/pcmcia/rsrc_nonstatic.c
View file @
5716d415
...
...
@@ -1055,8 +1055,6 @@ struct pccard_resource_ops pccard_nonstatic_ops = {
.
validate_mem
=
pcmcia_nonstatic_validate_mem
,
.
find_io
=
nonstatic_find_io
,
.
find_mem
=
nonstatic_find_mem_region
,
.
add_io
=
adjust_io
,
.
add_mem
=
adjust_memory
,
.
init
=
nonstatic_init
,
.
exit
=
nonstatic_release_resource_db
,
};
...
...
include/pcmcia/ds.h
View file @
5716d415
...
...
@@ -117,11 +117,6 @@ struct pcmcia_device {
u64
dma_mask
;
struct
device
dev
;
#ifdef CONFIG_PCMCIA_IOCTL
/* device driver wanted by cardmgr */
struct
pcmcia_driver
*
cardmgr
;
#endif
/* data private to drivers */
void
*
priv
;
};
...
...
@@ -211,208 +206,4 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev);
#endif
/* __KERNEL__ */
/* Below, there are only definitions which are used by
* - the PCMCIA ioctl
* - deprecated PCMCIA userspace tools only
*
* here be dragons ... here be dragons ... here be dragons ... here be drag
*/
#if defined(CONFIG_PCMCIA_IOCTL) || !defined(__KERNEL__)
#if defined(__arm__) || defined(__mips__) || defined(__avr32__) || \
defined(__bfin__)
/* This (ioaddr_t) is exposed to userspace & hence cannot be changed. */
typedef
u_int
ioaddr_t
;
#else
typedef
u_short
ioaddr_t
;
#endif
/* for AdjustResourceInfo */
typedef
struct
adjust_t
{
u_int
Action
;
u_int
Resource
;
u_int
Attributes
;
union
{
struct
memory
{
u_long
Base
;
u_long
Size
;
}
memory
;
struct
io
{
ioaddr_t
BasePort
;
ioaddr_t
NumPorts
;
u_int
IOAddrLines
;
}
io
;
struct
irq
{
u_int
IRQ
;
}
irq
;
}
resource
;
}
adjust_t
;
/* Action field */
#define REMOVE_MANAGED_RESOURCE 1
#define ADD_MANAGED_RESOURCE 2
#define GET_FIRST_MANAGED_RESOURCE 3
#define GET_NEXT_MANAGED_RESOURCE 4
/* Resource field */
#define RES_MEMORY_RANGE 1
#define RES_IO_RANGE 2
#define RES_IRQ 3
/* Attribute field */
#define RES_IRQ_TYPE 0x03
#define RES_IRQ_TYPE_EXCLUSIVE 0
#define RES_IRQ_TYPE_TIME 1
#define RES_IRQ_TYPE_DYNAMIC 2
#define RES_IRQ_CSC 0x04
#define RES_SHARED 0x08
#define RES_RESERVED 0x10
#define RES_ALLOCATED 0x20
#define RES_REMOVED 0x40
typedef
struct
tuple_parse_t
{
tuple_t
tuple
;
cisdata_t
data
[
255
];
cisparse_t
parse
;
}
tuple_parse_t
;
typedef
struct
win_info_t
{
window_handle_t
handle
;
win_req_t
window
;
memreq_t
map
;
}
win_info_t
;
typedef
struct
bind_info_t
{
dev_info_t
dev_info
;
u_char
function
;
struct
pcmcia_device
*
instance
;
char
name
[
DEV_NAME_LEN
];
u_short
major
,
minor
;
void
*
next
;
}
bind_info_t
;
typedef
struct
mtd_info_t
{
dev_info_t
dev_info
;
u_int
Attributes
;
u_int
CardOffset
;
}
mtd_info_t
;
typedef
struct
region_info_t
{
u_int
Attributes
;
u_int
CardOffset
;
u_int
RegionSize
;
u_int
AccessSpeed
;
u_int
BlockSize
;
u_int
PartMultiple
;
u_char
JedecMfr
,
JedecInfo
;
memory_handle_t
next
;
}
region_info_t
;
#define REGION_TYPE 0x0001
#define REGION_TYPE_CM 0x0000
#define REGION_TYPE_AM 0x0001
#define REGION_PREFETCH 0x0008
#define REGION_CACHEABLE 0x0010
#define REGION_BAR_MASK 0xe000
#define REGION_BAR_SHIFT 13
/* For ReplaceCIS */
typedef
struct
cisdump_t
{
u_int
Length
;
cisdata_t
Data
[
CISTPL_MAX_CIS_SIZE
];
}
cisdump_t
;
/* for GetConfigurationInfo */
typedef
struct
config_info_t
{
u_char
Function
;
u_int
Attributes
;
u_int
Vcc
,
Vpp1
,
Vpp2
;
u_int
IntType
;
u_int
ConfigBase
;
u_char
Status
,
Pin
,
Copy
,
Option
,
ExtStatus
;
u_int
Present
;
u_int
CardValues
;
u_int
AssignedIRQ
;
u_int
IRQAttributes
;
ioaddr_t
BasePort1
;
ioaddr_t
NumPorts1
;
u_int
Attributes1
;
ioaddr_t
BasePort2
;
ioaddr_t
NumPorts2
;
u_int
Attributes2
;
u_int
IOAddrLines
;
}
config_info_t
;
/* For ValidateCIS */
typedef
struct
cisinfo_t
{
u_int
Chains
;
}
cisinfo_t
;
typedef
struct
cs_status_t
{
u_char
Function
;
event_t
CardState
;
event_t
SocketState
;
}
cs_status_t
;
typedef
union
ds_ioctl_arg_t
{
adjust_t
adjust
;
config_info_t
config
;
tuple_t
tuple
;
tuple_parse_t
tuple_parse
;
client_req_t
client_req
;
cs_status_t
status
;
conf_reg_t
conf_reg
;
cisinfo_t
cisinfo
;
region_info_t
region
;
bind_info_t
bind_info
;
mtd_info_t
mtd_info
;
win_info_t
win_info
;
cisdump_t
cisdump
;
}
ds_ioctl_arg_t
;
#define DS_ADJUST_RESOURCE_INFO _IOWR('d', 2, adjust_t)
#define DS_GET_CONFIGURATION_INFO _IOWR('d', 3, config_info_t)
#define DS_GET_FIRST_TUPLE _IOWR('d', 4, tuple_t)
#define DS_GET_NEXT_TUPLE _IOWR('d', 5, tuple_t)
#define DS_GET_TUPLE_DATA _IOWR('d', 6, tuple_parse_t)
#define DS_PARSE_TUPLE _IOWR('d', 7, tuple_parse_t)
#define DS_RESET_CARD _IO ('d', 8)
#define DS_GET_STATUS _IOWR('d', 9, cs_status_t)
#define DS_ACCESS_CONFIGURATION_REGISTER _IOWR('d', 10, conf_reg_t)
#define DS_VALIDATE_CIS _IOR ('d', 11, cisinfo_t)
#define DS_SUSPEND_CARD _IO ('d', 12)
#define DS_RESUME_CARD _IO ('d', 13)
#define DS_EJECT_CARD _IO ('d', 14)
#define DS_INSERT_CARD _IO ('d', 15)
#define DS_GET_FIRST_REGION _IOWR('d', 16, region_info_t)
#define DS_GET_NEXT_REGION _IOWR('d', 17, region_info_t)
#define DS_REPLACE_CIS _IOWR('d', 18, cisdump_t)
#define DS_GET_FIRST_WINDOW _IOR ('d', 19, win_info_t)
#define DS_GET_NEXT_WINDOW _IOWR('d', 20, win_info_t)
#define DS_GET_MEM_PAGE _IOWR('d', 21, win_info_t)
#define DS_BIND_REQUEST _IOWR('d', 60, bind_info_t)
#define DS_GET_DEVICE_INFO _IOWR('d', 61, bind_info_t)
#define DS_GET_NEXT_DEVICE _IOWR('d', 62, bind_info_t)
#define DS_UNBIND_REQUEST _IOW ('d', 63, bind_info_t)
#define DS_BIND_MTD _IOWR('d', 64, mtd_info_t)
/* used in userspace only */
#define CS_IN_USE 0x1e
#define INFO_MASTER_CLIENT 0x01
#define INFO_IO_CLIENT 0x02
#define INFO_MTD_CLIENT 0x04
#define INFO_MEM_CLIENT 0x08
#define MAX_NUM_CLIENTS 3
#define INFO_CARD_SHARE 0x10
#define INFO_CARD_EXCL 0x20
#endif
/* !defined(__KERNEL__) || defined(CONFIG_PCMCIA_IOCTL) */
#endif
/* _LINUX_DS_H */
include/pcmcia/ss.h
View file @
5716d415
...
...
@@ -220,12 +220,10 @@ struct pcmcia_socket {
/* 16-bit state: */
struct
{
/* "master" ioctl is used */
u8
busy
:
1
;
/* the PCMCIA card consists of two pseudo devices */
u8
has_pfc
:
1
;
u8
reserved
:
6
;
u8
reserved
:
7
;
}
pcmcia_state
;
/* non-zero if PCMCIA card is present */
...
...
@@ -234,10 +232,6 @@ struct pcmcia_socket {
/* IRQ to be used by PCMCIA devices. May not be IRQ 0. */
unsigned
int
pcmcia_irq
;
#ifdef CONFIG_PCMCIA_IOCTL
struct
user_info_t
*
user
;
wait_queue_head_t
queue
;
#endif
/* CONFIG_PCMCIA_IOCTL */
#endif
/* CONFIG_PCMCIA */
/* socket device */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment