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
Kirill Smelkov
linux
Commits
01a99f33
Commit
01a99f33
authored
Mar 26, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://bk.arm.linux.org.uk/linux-2.5-pcmcia
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
fff263fe
0f5c57f5
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
259 additions
and
251 deletions
+259
-251
drivers/pcmcia/ds.c
drivers/pcmcia/ds.c
+249
-176
include/pcmcia/driver_ops.h
include/pcmcia/driver_ops.h
+2
-73
include/pcmcia/ds.h
include/pcmcia/ds.h
+8
-2
No files found.
drivers/pcmcia/ds.c
View file @
01a99f33
...
...
@@ -48,6 +48,7 @@
#include <linux/proc_fs.h>
#include <linux/poll.h>
#include <linux/pci.h>
#include <linux/list.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
...
...
@@ -55,6 +56,7 @@
#include <pcmcia/bulkmem.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <pcmcia/ss.h>
/*====================================================================*/
...
...
@@ -97,15 +99,18 @@ typedef struct user_info_t {
}
user_info_t
;
/* Socket state information */
typedef
struct
socket_info_t
{
client_handle_t
handle
;
int
state
;
user_info_t
*
user
;
int
req_pending
,
req_result
;
wait_queue_head_t
queue
,
request
;
struct
timer_list
removal
;
socket_bind_t
*
bind
;
}
socket_info_t
;
struct
pcmcia_bus_socket
{
client_handle_t
handle
;
int
state
;
user_info_t
*
user
;
int
req_pending
,
req_result
;
wait_queue_head_t
queue
,
request
;
struct
timer_list
removal
;
socket_bind_t
*
bind
;
struct
device
*
socket_dev
;
struct
list_head
socket_list
;
unsigned
int
socket_no
;
/* deprecated */
};
#define SOCKET_PRESENT 0x01
#define SOCKET_BUSY 0x02
...
...
@@ -116,13 +121,13 @@ typedef struct socket_info_t {
/* Device driver ID passed to Card Services */
static
dev_info_t
dev_info
=
"Driver Services"
;
static
int
sockets
=
0
,
major_dev
=
-
1
;
static
socket_info_t
*
socket_table
=
NULL
;
static
int
major_dev
=
-
1
;
extern
struct
proc_dir_entry
*
proc_pccard
;
/* list of all sockets registered with the pcmcia bus driver */
static
DECLARE_RWSEM
(
bus_socket_list_rwsem
);
static
LIST_HEAD
(
bus_socket_list
);
/* We use this to distinguish in-kernel from modular drivers */
static
int
init_status
=
1
;
extern
struct
proc_dir_entry
*
proc_pccard
;
/*====================================================================*/
...
...
@@ -135,6 +140,7 @@ static void cs_error(client_handle_t handle, int func, int ret)
/*======================================================================*/
static
struct
pcmcia_driver
*
get_pcmcia_driver
(
dev_info_t
*
dev_info
);
static
struct
pcmcia_bus_socket
*
get_socket_info_by_nr
(
unsigned
int
nr
);
/**
* pcmcia_register_driver - register a PCMCIA driver with the bus core
...
...
@@ -147,7 +153,6 @@ int pcmcia_register_driver(struct pcmcia_driver *driver)
return
-
EINVAL
;
driver
->
use_count
=
0
;
driver
->
status
=
init_status
;
driver
->
drv
.
bus
=
&
pcmcia_bus_type
;
return
driver_register
(
&
driver
->
drv
);
...
...
@@ -160,17 +165,19 @@ EXPORT_SYMBOL(pcmcia_register_driver);
void
pcmcia_unregister_driver
(
struct
pcmcia_driver
*
driver
)
{
socket_bind_t
*
b
;
int
i
;
struct
pcmcia_bus_socket
*
bus_sock
;
if
(
driver
->
use_count
>
0
)
{
/* Blank out any left-over device instances */
driver
->
attach
=
NULL
;
driver
->
detach
=
NULL
;
for
(
i
=
0
;
i
<
sockets
;
i
++
)
for
(
b
=
socket_table
[
i
].
bind
;
b
;
b
=
b
->
next
)
down_read
(
&
bus_socket_list_rwsem
);
list_for_each_entry
(
bus_sock
,
&
bus_socket_list
,
socket_list
)
{
for
(
b
=
bus_sock
->
bind
;
b
;
b
=
b
->
next
)
if
(
b
->
driver
==
driver
)
b
->
instance
=
NULL
;
}
}
up_read
(
&
bus_socket_list_rwsem
);
}
driver_unregister
(
&
driver
->
drv
);
}
EXPORT_SYMBOL
(
pcmcia_unregister_driver
);
...
...
@@ -182,7 +189,7 @@ int register_pccard_driver(dev_info_t *dev_info,
{
struct
pcmcia_driver
*
driver
;
socket_bind_t
*
b
;
int
i
;
struct
pcmcia_bus_socket
*
bus_sock
;
DEBUG
(
0
,
"ds: register_pccard_driver('%s')
\n
"
,
(
char
*
)
dev_info
);
driver
=
get_pcmcia_driver
(
dev_info
);
...
...
@@ -199,15 +206,17 @@ int register_pccard_driver(dev_info_t *dev_info,
if
(
driver
->
use_count
==
0
)
return
0
;
/* Instantiate any already-bound devices */
for
(
i
=
0
;
i
<
sockets
;
i
++
)
for
(
b
=
socket_table
[
i
].
bind
;
b
;
b
=
b
->
next
)
{
down_read
(
&
bus_socket_list_rwsem
);
list_for_each_entry
(
bus_sock
,
&
bus_socket_list
,
socket_list
)
{
for
(
b
=
bus_sock
->
bind
;
b
;
b
=
b
->
next
)
{
if
(
b
->
driver
!=
driver
)
continue
;
b
->
instance
=
driver
->
attach
();
if
(
b
->
instance
==
NULL
)
printk
(
KERN_NOTICE
"ds: unable to create instance "
"of '%s'!
\n
"
,
driver
->
drv
.
name
);
}
}
up_read
(
&
bus_socket_list_rwsem
);
return
0
;
}
/* register_pccard_driver */
...
...
@@ -238,8 +247,7 @@ static int proc_read_drivers_callback(struct device_driver *driver, void *d)
struct
pcmcia_driver
*
p_dev
=
container_of
(
driver
,
struct
pcmcia_driver
,
drv
);
*
p
+=
sprintf
(
*
p
,
"%-24.24s %d %d
\n
"
,
driver
->
name
,
p_dev
->
status
,
p_dev
->
use_count
);
*
p
+=
sprintf
(
*
p
,
"%-24.24s 1 %d
\n
"
,
driver
->
name
,
p_dev
->
use_count
);
d
=
(
void
*
)
p
;
return
0
;
...
...
@@ -282,7 +290,7 @@ static void queue_event(user_info_t *user, event_t event)
user
->
event
[
user
->
event_head
]
=
event
;
}
static
void
handle_event
(
s
ocket_info_
t
*
s
,
event_t
event
)
static
void
handle_event
(
s
truct
pcmcia_bus_socke
t
*
s
,
event_t
event
)
{
user_info_t
*
user
;
for
(
user
=
s
->
user
;
user
;
user
=
user
->
next
)
...
...
@@ -290,7 +298,7 @@ static void handle_event(socket_info_t *s, event_t event)
wake_up_interruptible
(
&
s
->
queue
);
}
static
int
handle_request
(
s
ocket_info_
t
*
s
,
event_t
event
)
static
int
handle_request
(
s
truct
pcmcia_bus_socke
t
*
s
,
event_t
event
)
{
if
(
s
->
req_pending
!=
0
)
return
CS_IN_USE
;
...
...
@@ -309,7 +317,7 @@ static int handle_request(socket_info_t *s, event_t event)
static
void
handle_removal
(
u_long
sn
)
{
s
ocket_info_t
*
s
=
&
socket_table
[
sn
]
;
s
truct
pcmcia_bus_socket
*
s
=
get_socket_info_by_nr
(
sn
)
;
handle_event
(
s
,
CS_EVENT_CARD_REMOVAL
);
s
->
state
&=
~
SOCKET_REMOVAL_PENDING
;
}
...
...
@@ -323,13 +331,11 @@ static void handle_removal(u_long sn)
static
int
ds_event
(
event_t
event
,
int
priority
,
event_callback_args_t
*
args
)
{
socket_info_t
*
s
;
int
i
;
struct
pcmcia_bus_socket
*
s
;
DEBUG
(
1
,
"ds: ds_event(0x%06x, %d, 0x%p)
\n
"
,
event
,
priority
,
args
->
client_handle
);
s
=
args
->
client_data
;
i
=
s
-
socket_table
;
switch
(
event
)
{
...
...
@@ -366,21 +372,21 @@ static int ds_event(event_t event, int priority,
======================================================================*/
static
int
bind_mtd
(
int
i
,
mtd_info_t
*
mtd_info
)
static
int
bind_mtd
(
struct
pcmcia_bus_socket
*
bus_sock
,
mtd_info_t
*
mtd_info
)
{
mtd_bind_t
bind_req
;
int
ret
;
bind_req
.
dev_info
=
&
mtd_info
->
dev_info
;
bind_req
.
Attributes
=
mtd_info
->
Attributes
;
bind_req
.
Socket
=
i
;
bind_req
.
Socket
=
bus_sock
->
socket_no
;
bind_req
.
CardOffset
=
mtd_info
->
CardOffset
;
ret
=
pcmcia_bind_mtd
(
&
bind_req
);
if
(
ret
!=
CS_SUCCESS
)
{
cs_error
(
NULL
,
BindMTD
,
ret
);
printk
(
KERN_NOTICE
"ds: unable to bind MTD '%s' to socket %d"
" offset 0x%x
\n
"
,
(
char
*
)
bind_req
.
dev_info
,
i
,
bind_req
.
CardOffset
);
(
char
*
)
bind_req
.
dev_info
,
bus_sock
->
socket_no
,
bind_req
.
CardOffset
);
return
-
ENODEV
;
}
return
0
;
...
...
@@ -395,14 +401,16 @@ static int bind_mtd(int i, mtd_info_t *mtd_info)
======================================================================*/
static
int
bind_request
(
int
i
,
bind_info_t
*
bind_info
)
static
int
bind_request
(
struct
pcmcia_bus_socket
*
s
,
bind_info_t
*
bind_info
)
{
struct
pcmcia_driver
*
driver
;
socket_bind_t
*
b
;
bind_req_t
bind_req
;
socket_info_t
*
s
=
&
socket_table
[
i
];
int
ret
;
if
(
!
s
)
return
-
EINVAL
;
DEBUG
(
2
,
"bind_request(%d, '%s')
\n
"
,
i
,
(
char
*
)
bind_info
->
dev_info
);
driver
=
get_pcmcia_driver
(
&
bind_info
->
dev_info
);
...
...
@@ -423,14 +431,14 @@ static int bind_request(int i, bind_info_t *bind_info)
return
-
EBUSY
;
}
bind_req
.
Socket
=
i
;
bind_req
.
Socket
=
s
->
socket_no
;
bind_req
.
Function
=
bind_info
->
function
;
bind_req
.
dev_info
=
(
dev_info_t
*
)
driver
->
drv
.
name
;
ret
=
pcmcia_bind_device
(
&
bind_req
);
if
(
ret
!=
CS_SUCCESS
)
{
cs_error
(
NULL
,
BindDevice
,
ret
);
printk
(
KERN_NOTICE
"ds: unable to bind '%s' to socket %d
\n
"
,
(
char
*
)
dev_info
,
i
);
(
char
*
)
dev_info
,
s
->
socket_no
);
return
-
ENODEV
;
}
...
...
@@ -462,9 +470,8 @@ static int bind_request(int i, bind_info_t *bind_info)
/*====================================================================*/
static
int
get_device_info
(
int
i
,
bind_info_t
*
bind_info
,
int
first
)
static
int
get_device_info
(
struct
pcmcia_bus_socket
*
s
,
bind_info_t
*
bind_info
,
int
first
)
{
socket_info_t
*
s
=
&
socket_table
[
i
];
socket_bind_t
*
b
;
dev_node_t
*
node
;
...
...
@@ -532,9 +539,8 @@ static int get_device_info(int i, bind_info_t *bind_info, int first)
/*====================================================================*/
static
int
unbind_request
(
int
i
,
bind_info_t
*
bind_info
)
static
int
unbind_request
(
struct
pcmcia_bus_socket
*
s
,
bind_info_t
*
bind_info
)
{
socket_info_t
*
s
=
&
socket_table
[
i
];
socket_bind_t
**
b
,
*
c
;
DEBUG
(
2
,
"unbind_request(%d, '%s')
\n
"
,
i
,
...
...
@@ -568,13 +574,15 @@ static int unbind_request(int i, bind_info_t *bind_info)
static
int
ds_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
socket_t
i
=
minor
(
inode
->
i_rdev
);
s
ocket_info_
t
*
s
;
s
truct
pcmcia_bus_socke
t
*
s
;
user_info_t
*
user
;
DEBUG
(
0
,
"ds_open(socket %d)
\n
"
,
i
);
if
((
i
>=
sockets
)
||
(
sockets
==
0
))
return
-
ENODEV
;
s
=
&
socket_table
[
i
];
s
=
get_socket_info_by_nr
(
i
);
if
(
!
s
)
return
-
ENODEV
;
if
((
file
->
f_flags
&
O_ACCMODE
)
!=
O_RDONLY
)
{
if
(
s
->
state
&
SOCKET_BUSY
)
return
-
EBUSY
;
...
...
@@ -600,13 +608,15 @@ static int ds_open(struct inode *inode, struct file *file)
static
int
ds_release
(
struct
inode
*
inode
,
struct
file
*
file
)
{
socket_t
i
=
minor
(
inode
->
i_rdev
);
s
ocket_info_
t
*
s
;
s
truct
pcmcia_bus_socke
t
*
s
;
user_info_t
*
user
,
**
link
;
DEBUG
(
0
,
"ds_release(socket %d)
\n
"
,
i
);
if
((
i
>=
sockets
)
||
(
sockets
==
0
))
return
0
;
s
=
&
socket_table
[
i
];
s
=
get_socket_info_by_nr
(
i
);
if
(
!
s
)
return
0
;
user
=
file
->
private_data
;
if
(
CHECK_USER
(
user
))
goto
out
;
...
...
@@ -632,16 +642,18 @@ static ssize_t ds_read(struct file *file, char *buf,
size_t
count
,
loff_t
*
ppos
)
{
socket_t
i
=
minor
(
file
->
f_dentry
->
d_inode
->
i_rdev
);
s
ocket_info_
t
*
s
;
s
truct
pcmcia_bus_socke
t
*
s
;
user_info_t
*
user
;
DEBUG
(
2
,
"ds_read(socket %d)
\n
"
,
i
);
if
((
i
>=
sockets
)
||
(
sockets
==
0
))
return
-
ENODEV
;
if
(
count
<
4
)
return
-
EINVAL
;
s
=
&
socket_table
[
i
];
s
=
get_socket_info_by_nr
(
i
);
if
(
!
s
)
return
-
ENODEV
;
user
=
file
->
private_data
;
if
(
CHECK_USER
(
user
))
return
-
EIO
;
...
...
@@ -661,18 +673,20 @@ static ssize_t ds_write(struct file *file, const char *buf,
size_t
count
,
loff_t
*
ppos
)
{
socket_t
i
=
minor
(
file
->
f_dentry
->
d_inode
->
i_rdev
);
s
ocket_info_
t
*
s
;
s
truct
pcmcia_bus_socke
t
*
s
;
user_info_t
*
user
;
DEBUG
(
2
,
"ds_write(socket %d)
\n
"
,
i
);
if
((
i
>=
sockets
)
||
(
sockets
==
0
))
return
-
ENODEV
;
if
(
count
!=
4
)
return
-
EINVAL
;
if
((
file
->
f_flags
&
O_ACCMODE
)
==
O_RDONLY
)
return
-
EBADF
;
s
=
&
socket_table
[
i
];
s
=
get_socket_info_by_nr
(
i
);
if
(
!
s
)
return
-
ENODEV
;
user
=
file
->
private_data
;
if
(
CHECK_USER
(
user
))
return
-
EIO
;
...
...
@@ -694,14 +708,15 @@ static ssize_t ds_write(struct file *file, const char *buf,
static
u_int
ds_poll
(
struct
file
*
file
,
poll_table
*
wait
)
{
socket_t
i
=
minor
(
file
->
f_dentry
->
d_inode
->
i_rdev
);
s
ocket_info_
t
*
s
;
s
truct
pcmcia_bus_socke
t
*
s
;
user_info_t
*
user
;
DEBUG
(
2
,
"ds_poll(socket %d)
\n
"
,
i
);
if
((
i
>=
sockets
)
||
(
sockets
==
0
))
return
POLLERR
;
s
=
&
socket_table
[
i
];
s
=
get_socket_info_by_nr
(
i
);
if
(
!
s
)
return
POLLERR
;
user
=
file
->
private_data
;
if
(
CHECK_USER
(
user
))
return
POLLERR
;
...
...
@@ -717,16 +732,16 @@ static int ds_ioctl(struct inode * inode, struct file * file,
u_int
cmd
,
u_long
arg
)
{
socket_t
i
=
minor
(
inode
->
i_rdev
);
s
ocket_info_
t
*
s
;
s
truct
pcmcia_bus_socke
t
*
s
;
u_int
size
;
int
ret
,
err
;
ds_ioctl_arg_t
buf
;
DEBUG
(
2
,
"ds_ioctl(socket %d, %#x, %#lx)
\n
"
,
i
,
cmd
,
arg
);
if
((
i
>=
sockets
)
||
(
sockets
==
0
))
return
-
ENODEV
;
s
=
&
socket_table
[
i
]
;
s
=
get_socket_info_by_nr
(
i
);
if
(
!
s
)
return
-
ENODEV
;
size
=
(
cmd
&
IOCSIZE_MASK
)
>>
IOCSIZE_SHIFT
;
if
(
size
>
sizeof
(
ds_ioctl_arg_t
))
return
-
EINVAL
;
...
...
@@ -827,20 +842,20 @@ static int ds_ioctl(struct inode * inode, struct file * file,
break
;
case
DS_BIND_REQUEST
:
if
(
!
capable
(
CAP_SYS_ADMIN
))
return
-
EPERM
;
err
=
bind_request
(
i
,
&
buf
.
bind_info
);
err
=
bind_request
(
s
,
&
buf
.
bind_info
);
break
;
case
DS_GET_DEVICE_INFO
:
err
=
get_device_info
(
i
,
&
buf
.
bind_info
,
1
);
err
=
get_device_info
(
s
,
&
buf
.
bind_info
,
1
);
break
;
case
DS_GET_NEXT_DEVICE
:
err
=
get_device_info
(
i
,
&
buf
.
bind_info
,
0
);
err
=
get_device_info
(
s
,
&
buf
.
bind_info
,
0
);
break
;
case
DS_UNBIND_REQUEST
:
err
=
unbind_request
(
i
,
&
buf
.
bind_info
);
err
=
unbind_request
(
s
,
&
buf
.
bind_info
);
break
;
case
DS_BIND_MTD
:
if
(
!
capable
(
CAP_SYS_ADMIN
))
return
-
EPERM
;
err
=
bind_mtd
(
i
,
&
buf
.
mtd_info
);
err
=
bind_mtd
(
s
,
&
buf
.
mtd_info
);
break
;
default:
err
=
-
EINVAL
;
...
...
@@ -889,141 +904,199 @@ EXPORT_SYMBOL(unregister_pccard_driver);
/*====================================================================*/
struct
bus_type
pcmcia_bus_type
=
{
.
name
=
"pcmcia"
,
};
EXPORT_SYMBOL
(
pcmcia_bus_type
);
static
int
__init
init_pcmcia_bus
(
void
)
static
int
__devinit
pcmcia_bus_add_socket
(
struct
device
*
dev
,
unsigned
int
socket_nr
)
{
bus_register
(
&
pcmcia_bus_type
);
return
0
;
}
client_reg_t
client_reg
;
bind_req_t
bind
;
struct
pcmcia_bus_socket
*
s
,
*
tmp_s
;
int
ret
;
int
i
;
static
int
__init
init_pcmcia_ds
(
void
)
{
client_reg_t
client_reg
;
servinfo_t
serv
;
bind_req_t
bind
;
socket_info_t
*
s
;
int
i
,
ret
;
s
=
kmalloc
(
sizeof
(
struct
pcmcia_bus_socket
),
GFP_KERNEL
);
if
(
!
s
)
return
-
ENOMEM
;
memset
(
s
,
0
,
sizeof
(
struct
pcmcia_bus_socket
));
DEBUG
(
0
,
"%s
\n
"
,
version
);
/*
* Ugly. But we want to wait for the socket threads to have started up.
* We really should let the drivers themselves drive some of this..
*/
current
->
state
=
TASK_INTERRUPTIBLE
;
schedule_timeout
(
HZ
/
4
);
/*
* Ugly. But we want to wait for the socket threads to have started up.
* We really should let the drivers themselves drive some of this..
*/
current
->
state
=
TASK_INTERRUPTIBLE
;
schedule_timeout
(
HZ
/
4
);
pcmcia_get_card_services_info
(
&
serv
);
if
(
serv
.
Revision
!=
CS_RELEASE_CODE
)
{
printk
(
KERN_NOTICE
"ds: Card Services release does not match!
\n
"
);
return
-
1
;
}
if
(
serv
.
Count
==
0
)
{
printk
(
KERN_NOTICE
"ds: no socket drivers loaded!
\n
"
);
return
-
1
;
}
sockets
=
serv
.
Count
;
socket_table
=
kmalloc
(
sockets
*
sizeof
(
socket_info_t
),
GFP_KERNEL
);
if
(
!
socket_table
)
return
-
1
;
for
(
i
=
0
,
s
=
socket_table
;
i
<
sockets
;
i
++
,
s
++
)
{
s
->
state
=
0
;
s
->
user
=
NULL
;
s
->
req_pending
=
0
;
init_waitqueue_head
(
&
s
->
queue
);
init_waitqueue_head
(
&
s
->
request
);
s
->
handle
=
NULL
;
init_timer
(
&
s
->
removal
);
s
->
removal
.
data
=
i
;
/* find the lowest, unused socket no. Please note that this is a
* temporary workaround until "struct pcmcia_socket" is introduced
* into cs.c which will include this number, and which will be
* accessible to ds.c directly */
i
=
0
;
next_try:
list_for_each_entry
(
tmp_s
,
&
bus_socket_list
,
socket_list
)
{
if
(
tmp_s
->
socket_no
==
i
)
{
i
++
;
goto
next_try
;
}
}
s
->
socket_no
=
i
;
/* initialize data */
s
->
socket_dev
=
dev
;
s
->
removal
.
data
=
s
->
socket_no
;
s
->
removal
.
function
=
&
handle_removal
;
s
->
bind
=
NULL
;
}
init_timer
(
&
s
->
removal
);
/* Set up hotline to Card Services */
client_reg
.
dev_info
=
bind
.
dev_info
=
&
dev_info
;
client_reg
.
Attributes
=
INFO_MASTER_CLIENT
;
client_reg
.
EventMask
=
CS_EVENT_CARD_INSERTION
|
CS_EVENT_CARD_REMOVAL
|
CS_EVENT_RESET_PHYSICAL
|
CS_EVENT_CARD_RESET
|
CS_EVENT_EJECTION_REQUEST
|
CS_EVENT_INSERTION_REQUEST
|
CS_EVENT_PM_SUSPEND
|
CS_EVENT_PM_RESUME
;
client_reg
.
event_handler
=
&
ds_event
;
client_reg
.
Version
=
0x0210
;
for
(
i
=
0
;
i
<
sockets
;
i
++
)
{
bind
.
Socket
=
i
;
/* Set up hotline to Card Services */
client_reg
.
dev_info
=
bind
.
dev_info
=
&
dev_info
;
bind
.
Socket
=
s
->
socket_no
;
bind
.
Function
=
BIND_FN_ALL
;
ret
=
pcmcia_bind_device
(
&
bind
);
if
(
ret
!=
CS_SUCCESS
)
{
cs_error
(
NULL
,
BindDevice
,
ret
);
break
;
cs_error
(
NULL
,
BindDevice
,
ret
);
kfree
(
s
);
return
-
EINVAL
;
}
client_reg
.
event_callback_args
.
client_data
=
&
socket_table
[
i
];
ret
=
pcmcia_register_client
(
&
socket_table
[
i
].
handle
,
&
client_reg
);
client_reg
.
Attributes
=
INFO_MASTER_CLIENT
;
client_reg
.
EventMask
=
CS_EVENT_CARD_INSERTION
|
CS_EVENT_CARD_REMOVAL
|
CS_EVENT_RESET_PHYSICAL
|
CS_EVENT_CARD_RESET
|
CS_EVENT_EJECTION_REQUEST
|
CS_EVENT_INSERTION_REQUEST
|
CS_EVENT_PM_SUSPEND
|
CS_EVENT_PM_RESUME
;
client_reg
.
event_handler
=
&
ds_event
;
client_reg
.
Version
=
0x0210
;
client_reg
.
event_callback_args
.
client_data
=
s
;
ret
=
pcmcia_register_client
(
&
s
->
handle
,
&
client_reg
);
if
(
ret
!=
CS_SUCCESS
)
{
cs_error
(
NULL
,
RegisterClient
,
ret
);
break
;
cs_error
(
NULL
,
RegisterClient
,
ret
);
kfree
(
s
);
return
-
EINVAL
;
}
}
/* Set up character device for user mode clients */
i
=
register_chrdev
(
0
,
"pcmcia"
,
&
ds_fops
);
if
(
i
==
-
EBUSY
)
printk
(
KERN_NOTICE
"unable to find a free device # for "
"Driver Services
\n
"
);
else
major_dev
=
i
;
#ifdef CONFIG_PROC_FS
if
(
proc_pccard
)
create_proc_read_entry
(
"drivers"
,
0
,
proc_pccard
,
proc_read_drivers
,
NULL
);
init_status
=
0
;
#endif
return
0
;
list_add
(
&
s
->
socket_list
,
&
bus_socket_list
);
return
0
;
}
static
void
__exit
exit_pcmcia_ds
(
void
)
static
int
__devinit
pcmcia_bus_add_socket_dev
(
struct
device
*
dev
)
{
struct
pcmcia_socket_class_data
*
cls_d
=
dev
->
class_data
;
unsigned
int
i
;
unsigned
int
ret
=
0
;
if
(
!
cls_d
)
return
-
ENODEV
;
down_write
(
&
bus_socket_list_rwsem
);
for
(
i
=
0
;
i
<
cls_d
->
nsock
;
i
++
)
ret
+=
pcmcia_bus_add_socket
(
dev
,
i
);
up_write
(
&
bus_socket_list_rwsem
);
return
ret
;
}
static
int
__devexit
pcmcia_bus_remove_socket_dev
(
struct
device
*
dev
)
{
int
i
;
struct
pcmcia_socket_class_data
*
cls_d
=
dev
->
class_data
;
struct
list_head
*
list_loop
;
struct
list_head
*
tmp_storage
;
if
(
!
cls_d
)
return
-
ENODEV
;
down_write
(
&
bus_socket_list_rwsem
);
list_for_each_safe
(
list_loop
,
tmp_storage
,
&
bus_socket_list
)
{
struct
pcmcia_bus_socket
*
bus_sock
=
container_of
(
list_loop
,
struct
pcmcia_bus_socket
,
socket_list
);
if
(
bus_sock
->
socket_dev
==
dev
)
{
pcmcia_deregister_client
(
bus_sock
->
handle
);
list_del
(
&
bus_sock
->
socket_list
);
kfree
(
bus_sock
);
}
}
up_write
(
&
bus_socket_list_rwsem
);
return
0
;
}
/* the pcmcia_bus_interface is used to handle pcmcia socket devices */
static
struct
device_interface
pcmcia_bus_interface
=
{
.
name
=
"pcmcia-bus"
,
.
devclass
=
&
pcmcia_socket_class
,
.
add_device
=
&
pcmcia_bus_add_socket_dev
,
.
remove_device
=
__devexit_p
(
&
pcmcia_bus_remove_socket_dev
),
.
kset
=
{
.
subsys
=
&
pcmcia_socket_class
.
subsys
,
},
.
devnum
=
0
,
};
struct
bus_type
pcmcia_bus_type
=
{
.
name
=
"pcmcia"
,
};
EXPORT_SYMBOL
(
pcmcia_bus_type
);
static
int
__init
init_pcmcia_bus
(
void
)
{
int
i
;
bus_register
(
&
pcmcia_bus_type
);
interface_register
(
&
pcmcia_bus_interface
);
/* Set up character device for user mode clients */
i
=
register_chrdev
(
0
,
"pcmcia"
,
&
ds_fops
);
if
(
i
==
-
EBUSY
)
printk
(
KERN_NOTICE
"unable to find a free device # for "
"Driver Services
\n
"
);
else
major_dev
=
i
;
#ifdef CONFIG_PROC_FS
if
(
proc_pccard
)
remove_proc_entry
(
"drivers"
,
proc_pccard
);
if
(
proc_pccard
)
create_proc_read_entry
(
"drivers"
,
0
,
proc_pccard
,
proc_read_drivers
,
NULL
);
#endif
if
(
major_dev
!=
-
1
)
unregister_chrdev
(
major_dev
,
"pcmcia"
);
for
(
i
=
0
;
i
<
sockets
;
i
++
)
pcmcia_deregister_client
(
socket_table
[
i
].
handle
);
sockets
=
0
;
kfree
(
socket_table
);
bus_unregister
(
&
pcmcia_bus_type
);
return
0
;
}
fs_initcall
(
init_pcmcia_bus
);
/* one level after subsys_initcall so that
* pcmcia_socket_class is already registered */
#ifdef MODULE
/* init_pcmcia_bus must be done early, init_pcmcia_ds late. If we load this
* as a module, we can only specify one initcall, though...
*/
static
int
__init
init_pcmcia_module
(
void
)
{
init_pcmcia_bus
();
return
init_pcmcia_ds
();
}
module_init
(
init_pcmcia_module
);
static
void
__exit
exit_pcmcia_bus
(
void
)
{
interface_unregister
(
&
pcmcia_bus_interface
);
#
else
/* !MODULE */
subsys_initcall
(
init_pcmcia_bus
);
late_initcall
(
init_pcmcia_ds
);
#
ifdef CONFIG_PROC_FS
if
(
proc_pccard
)
remove_proc_entry
(
"drivers"
,
proc_pccard
);
#endif
if
(
major_dev
!=
-
1
)
unregister_chrdev
(
major_dev
,
"pcmcia"
);
bus_unregister
(
&
pcmcia_bus_type
);
}
module_exit
(
exit_pcmcia_bus
);
module_exit
(
exit_pcmcia_ds
);
/* helpers for backwards-compatible functions */
static
struct
pcmcia_bus_socket
*
get_socket_info_by_nr
(
unsigned
int
nr
)
{
struct
pcmcia_bus_socket
*
s
;
down_read
(
&
bus_socket_list_rwsem
);
list_for_each_entry
(
s
,
&
bus_socket_list
,
socket_list
)
if
(
s
->
socket_no
==
nr
)
{
up_read
(
&
bus_socket_list_rwsem
);
return
s
;
}
up_read
(
&
bus_socket_list_rwsem
);
return
NULL
;
}
/* backwards-compatible accessing of driver --- by name! */
struct
cmp_data
{
...
...
include/pcmcia/driver_ops.h
View file @
01a99f33
/*
* driver_ops.h 1.15 2000/06/12 21:55:40
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License
* at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* 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.
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in which
* case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the MPL or the GPL.
*/
#ifndef _LINUX_DRIVER_OPS_H
#define _LINUX_DRIVER_OPS_H
#ifndef DEV_NAME_LEN
#define DEV_NAME_LEN 32
#endif
#ifdef __KERNEL__
typedef
struct
dev_node_t
{
char
dev_name
[
DEV_NAME_LEN
];
u_short
major
,
minor
;
struct
dev_node_t
*
next
;
}
dev_node_t
;
typedef
struct
dev_locator_t
{
enum
{
LOC_ISA
,
LOC_PCI
}
bus
;
union
{
struct
{
u_short
io_base_1
,
io_base_2
;
u_long
mem_base
;
u_char
irq
,
dma
;
}
isa
;
struct
{
u_char
bus
;
u_char
devfn
;
}
pci
;
}
b
;
}
dev_locator_t
;
typedef
struct
driver_operations
{
char
*
name
;
dev_node_t
*
(
*
attach
)
(
dev_locator_t
*
loc
);
void
(
*
suspend
)
(
dev_node_t
*
dev
);
void
(
*
resume
)
(
dev_node_t
*
dev
);
void
(
*
detach
)
(
dev_node_t
*
dev
);
}
driver_operations
;
int
register_driver
(
struct
driver_operations
*
ops
);
void
unregister_driver
(
struct
driver_operations
*
ops
);
#endif
/* __KERNEL__ */
#endif
/* _LINUX_DRIVER_OPS_H */
/* now empty */
#warning please remove the reference to this file
include/pcmcia/ds.h
View file @
01a99f33
...
...
@@ -30,9 +30,9 @@
#ifndef _LINUX_DS_H
#define _LINUX_DS_H
#include <pcmcia/driver_ops.h>
#include <pcmcia/bulkmem.h>
#include <linux/device.h>
#include <pcmcia/cs_types.h>
typedef
struct
tuple_parse_t
{
tuple_t
tuple
;
...
...
@@ -108,6 +108,12 @@ typedef union ds_ioctl_arg_t {
#ifdef __KERNEL__
typedef
struct
dev_node_t
{
char
dev_name
[
DEV_NAME_LEN
];
u_short
major
,
minor
;
struct
dev_node_t
*
next
;
}
dev_node_t
;
typedef
struct
dev_link_t
{
dev_node_t
*
dev
;
u_int
state
,
open
;
...
...
@@ -144,7 +150,7 @@ int unregister_pccard_driver(dev_info_t *dev_info);
extern
struct
bus_type
pcmcia_bus_type
;
struct
pcmcia_driver
{
int
use_count
,
status
;
int
use_count
;
dev_link_t
*
(
*
attach
)(
void
);
void
(
*
detach
)(
dev_link_t
*
);
struct
module
*
owner
;
...
...
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