Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
F
FPGA Configuration Space
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
FPGA Configuration Space
Commits
7de9a85a
Commit
7de9a85a
authored
Aug 19, 2012
by
Alessandro Rubini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
sdbfs/kernel: first working (read-only) implementation
Signed-off-by:
Alessandro Rubini
<
rubini@gnudd.com
>
parent
3994fe19
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
224 additions
and
18 deletions
+224
-18
sdb-fakedev.c
sdbfs/kernel/sdb-fakedev.c
+3
-1
sdbfs-core.c
sdbfs/kernel/sdbfs-core.c
+193
-12
sdbfs-device.c
sdbfs/kernel/sdbfs-device.c
+12
-1
sdbfs-int.h
sdbfs/kernel/sdbfs-int.h
+12
-0
sdbfs.h
sdbfs/kernel/sdbfs.h
+4
-4
No files found.
sdbfs/kernel/sdb-fakedev.c
View file @
7de9a85a
...
...
@@ -27,12 +27,13 @@ struct fakedev {
static
struct
fakedev
fakedev_devs
[
8
];
static
struct
device
fakedev_device
;
static
ssize_t
fakedev_read
(
struct
sdbfs_dev
*
sd
,
uint32_t
begin
,
u8
*
buf
,
static
ssize_t
fakedev_read
(
struct
sdbfs_dev
*
sd
,
uint32_t
begin
,
void
*
buf
,
size_t
count
)
{
struct
fakedev
*
fd
;
int
len
;
printk
(
"%s: %08x - %i
\n
"
,
__func__
,
(
int
)
begin
,
count
);
fd
=
container_of
(
sd
,
struct
fakedev
,
sd
);
len
=
fd
->
fw
->
size
;
if
(
begin
>
len
)
...
...
@@ -68,6 +69,7 @@ static int fakedev_init(void)
for
(
i
=
0
;
i
<
nimg
;
i
++
)
{
d
=
fakedev_devs
+
i
;
printk
(
"request for %i -- n %i
\n
"
,
i
,
nimg
);
if
(
request_firmware
(
&
d
->
fw
,
fsimg
[
i
],
&
fakedev_device
)
<
0
)
{
printk
(
"%s: can't load %s
\n
"
,
KBUILD_MODNAME
,
fsimg
[
i
]);
...
...
sdbfs/kernel/sdbfs-core.c
View file @
7de9a85a
...
...
@@ -10,46 +10,149 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/sdb.h>
/* in ../include, by now */
#include <linux/uaccess.h>
#include "sdbfs.h"
#include "sdbfs-int.h"
#define SDB_SIZE (sizeof(struct sdb_device))
static
int
sdbfs_readdir
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
)
{
struct
inode
*
ino
=
filp
->
f_dentry
->
d_inode
;
struct
sdbfs_inode
*
inode
;
struct
sdb_device
*
s_d
;
unsigned
long
file_off
=
filp
->
f_pos
;
unsigned
long
offset
=
ino
->
i_ino
&
~
1
;
int
i
,
j
,
n
;
printk
(
"%s
\n
"
,
__func__
);
return
-
ENOENT
;
if
(
file_off
!=
0
)
return
0
;
inode
=
container_of
(
ino
,
struct
sdbfs_inode
,
ino
);
n
=
be16_to_cpu
(
inode
->
s_i
.
sdb_records
)
-
1
;
/* FIXME: use file_off */
for
(
i
=
0
;
i
<
n
;
i
++
)
{
char
s
[
20
];
offset
+=
SDB_SIZE
;
s_d
=
(
struct
sdb_device
*
)
inode
->
files
+
i
;
strncpy
(
s
,
s_d
->
sdb_component
.
product
.
name
,
19
);
for
(
j
=
19
;
j
;
j
--
)
{
s
[
j
]
=
'\0'
;
if
(
s
[
j
-
1
]
!=
' '
)
break
;
}
if
(
filldir
(
dirent
,
s
,
j
,
offset
,
offset
,
DT_UNKNOWN
)
<
0
)
return
i
;
filp
->
f_pos
++
;
}
return
i
;
}
static
const
struct
file_operations
sdbfs_dir_
operation
s
=
{
static
const
struct
file_operations
sdbfs_dir_
fop
s
=
{
.
read
=
generic_read_dir
,
.
readdir
=
sdbfs_readdir
,
.
llseek
=
default_llseek
,
};
static
ssize_t
sdbfs_read
(
struct
file
*
f
,
char
__user
*
buf
,
size_t
count
,
loff_t
*
offp
)
{
struct
inode
*
ino
=
f
->
f_dentry
->
d_inode
;
struct
super_block
*
sb
=
ino
->
i_sb
;
struct
sdbfs_dev
*
sd
=
sb
->
s_fs_info
;
struct
sdbfs_inode
*
inode
;
char
kbuf
[
16
];
unsigned
long
start
,
size
;
ssize_t
ret
;
inode
=
container_of
(
ino
,
struct
sdbfs_inode
,
ino
);
start
=
be64_to_cpu
(
inode
->
s_d
.
sdb_component
.
addr_first
);
size
=
be64_to_cpu
(
inode
->
s_d
.
sdb_component
.
addr_last
)
+
1
-
start
;
/* Horribly inefficient, who cares... */
if
(
*
offp
>
size
)
return
0
;
if
(
*
offp
+
count
>
size
)
count
=
size
-
*
offp
;
ret
=
count
;
while
(
count
)
{
int
n
=
sizeof
(
kbuf
)
>
count
?
count
:
sizeof
(
kbuf
);
/* FIXME: error checking */
sd
->
ops
->
read
(
sd
,
start
+
*
offp
,
kbuf
,
n
);
if
(
copy_to_user
(
buf
,
kbuf
,
n
))
return
-
EFAULT
;
count
-=
n
;
buf
+=
n
;
*
offp
+=
n
;
}
return
ret
;
}
static
const
struct
file_operations
sdbfs_fops
=
{
.
read
=
sdbfs_read
,
};
static
struct
inode
*
sdbfs_iget
(
struct
super_block
*
sb
,
int
inum
);
static
struct
dentry
*
sdbfs_lookup
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
struct
nameidata
*
nd
)
{
printk
(
"%s
\n
"
,
__func__
);
return
NULL
;
struct
inode
*
ino
=
NULL
;
struct
sdbfs_inode
*
inode
=
container_of
(
dir
,
struct
sdbfs_inode
,
ino
);
struct
sdb_device
*
s_d
;
unsigned
long
inum
=
dir
->
i_ino
&
~
1
;
int
i
,
n
,
len
;
n
=
be16_to_cpu
(
inode
->
s_i
.
sdb_records
)
-
1
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
s_d
=
(
struct
sdb_device
*
)
inode
->
files
+
i
;
len
=
strlen
(
s_d
->
sdb_component
.
product
.
name
);
if
(
len
!=
dentry
->
d_name
.
len
)
continue
;
if
(
!
strncmp
(
s_d
->
sdb_component
.
product
.
name
,
dentry
->
d_name
.
name
,
len
))
break
;
}
if
(
i
!=
n
)
ino
=
sdbfs_iget
(
dir
->
i_sb
,
inum
+
SDB_SIZE
*
(
i
+
1
));
d_add
(
dentry
,
ino
);
return
0
;
}
static
const
struct
inode_operations
sdbfs_dir_i
node_operation
s
=
{
static
const
struct
inode_operations
sdbfs_dir_i
op
s
=
{
.
lookup
=
sdbfs_lookup
,
};
static
struct
kmem_cache
*
sdbfs_inode_cache
;
static
struct
inode
*
sdbfs_alloc_inode
(
struct
super_block
*
sb
)
{
struct
sdbfs_inode
*
inode
;
printk
(
"%s
\n
"
,
__func__
);
return
NULL
;
inode
=
kmem_cache_alloc
(
sdbfs_inode_cache
,
GFP_KERNEL
);
if
(
!
inode
)
return
NULL
;
inode_init_once
(
&
inode
->
ino
);
printk
(
"%s: return %p
\n
"
,
__func__
,
&
inode
->
ino
);
return
&
inode
->
ino
;
}
static
void
sdbfs_destroy_inode
(
struct
inode
*
ino
)
{
struct
sdbfs_inode
*
inode
;
printk
(
"%s
\n
"
,
__func__
);
inode
=
container_of
(
ino
,
struct
sdbfs_inode
,
ino
);
kmem_cache_free
(
sdbfs_inode_cache
,
inode
);
}
static
const
struct
super_operations
sdbfs_super_ops
=
{
...
...
@@ -57,6 +160,72 @@ static const struct super_operations sdbfs_super_ops = {
.
destroy_inode
=
sdbfs_destroy_inode
,
};
static
struct
inode
*
sdbfs_iget
(
struct
super_block
*
sb
,
int
inum
)
{
struct
inode
*
ino
;
struct
sdbfs_dev
*
sd
=
sb
->
s_fs_info
;
struct
sdbfs_inode
*
inode
;
uint32_t
offset
;
int
i
,
j
,
n
,
len
;
uint8_t
*
s
;
printk
(
"%s: inum %i
\n
"
,
__func__
,
inum
);
ino
=
iget_locked
(
sb
,
inum
);
if
(
!
ino
)
return
ERR_PTR
(
-
ENOMEM
);
if
(
!
(
ino
->
i_state
&
I_NEW
))
return
ino
;
/* The inode number is the offset, but root ino is currently 1 */
offset
=
inum
&
~
1
;
inode
=
container_of
(
ino
,
struct
sdbfs_inode
,
ino
);
n
=
sd
->
ops
->
read
(
sd
,
offset
,
&
inode
->
s_d
,
SDB_SIZE
);
if
(
n
!=
SDB_SIZE
)
return
ERR_PTR
(
-
EIO
);
set_nlink
(
ino
,
1
);
ino
->
i_size
=
be64_to_cpu
(
inode
->
s_d
.
sdb_component
.
addr_last
)
-
be64_to_cpu
(
inode
->
s_d
.
sdb_component
.
addr_first
)
+
1
;
ino
->
i_mtime
.
tv_sec
=
ino
->
i_atime
.
tv_sec
=
ino
->
i_ctime
.
tv_sec
=
0
;
ino
->
i_mtime
.
tv_nsec
=
ino
->
i_atime
.
tv_nsec
=
ino
->
i_ctime
.
tv_nsec
=
0
;
switch
(
inode
->
s_d
.
sdb_component
.
product
.
record_type
)
{
case
sdb_type_interconnect
:
printk
(
"%s: interconnect
\n
"
,
__func__
);
ino
->
i_mode
=
S_IFDIR
|
0555
;
ino
->
i_op
=
&
sdbfs_dir_iops
;
ino
->
i_fop
=
&
sdbfs_dir_fops
;
/* We are an interconnect, so read the other records too */
len
=
be16_to_cpu
(
inode
->
s_i
.
sdb_records
)
*
SDB_SIZE
;
inode
->
files
=
kmalloc
(
len
,
GFP_KERNEL
);
BUG_ON
(
!
inode
->
files
);
n
=
sd
->
ops
->
read
(
sd
,
offset
+
SDB_SIZE
,
inode
->
files
,
len
);
BUG_ON
(
n
!=
len
);
for
(
i
=
0
;
i
<
len
/
SDB_SIZE
;
i
++
)
{
/* zero-terminate: the lost type is not a problem */
s
=
(
struct
sdb_device
*
)(
inode
->
files
)[
i
]
.
sdb_component
.
product
.
name
;
for
(
j
=
19
;
j
;
j
--
)
{
s
[
j
]
=
'\0'
;
if
(
s
[
j
-
1
]
!=
' '
)
break
;
}
}
break
;
case
sdb_type_device
:
printk
(
"%s: device
\n
"
,
__func__
);
/* FIXME: Which bus type is this? */
ino
->
i_mode
=
S_IFREG
|
0444
;
ino
->
i_fop
=
&
sdbfs_fops
;
break
;
default:
BUG
();
}
unlock_new_inode
(
ino
);
return
ino
;
}
static
int
sdbfs_fill_super
(
struct
super_block
*
sb
,
void
*
data
,
int
silent
)
{
struct
inode
*
inode
;
...
...
@@ -76,10 +245,10 @@ static int sdbfs_fill_super(struct super_block *sb, void *data, int silent)
sb
->
s_magic
=
SDB_MAGIC
;
sb
->
s_op
=
&
sdbfs_super_ops
;
inode
=
iget_locked
(
sb
,
1
/* FIXME: inode number
*/
);
if
(
!
inode
)
{
printk
(
"no inode
\n
"
);
return
-
ENOMEM
;
inode
=
sdbfs_iget
(
sb
,
1
/* FIXME: root inode
*/
);
if
(
IS_ERR
(
inode
)
)
{
sdbfs_put
(
sd
);
return
PTR_ERR
(
inode
)
;
}
/*
...
...
@@ -87,8 +256,11 @@ static int sdbfs_fill_super(struct super_block *sb, void *data, int silent)
* after 3.2, but d_alloc_root was killed soon after 3.3
*/
root
=
d_make_root
(
inode
);
if
(
!
root
)
if
(
!
root
)
{
sdbfs_put
(
sd
);
/* FIXME: release inode? */
return
-
ENOMEM
;
}
root
->
d_fsdata
=
NULL
;
/* FIXME: d_fsdata */
sb
->
s_root
=
root
;
return
0
;
...
...
@@ -97,15 +269,20 @@ static int sdbfs_fill_super(struct super_block *sb, void *data, int silent)
static
struct
dentry
*
sdbfs_mount
(
struct
file_system_type
*
type
,
int
flags
,
const
char
*
name
,
void
*
data
)
{
struct
dentry
*
ret
;
char
*
fakedata
=
(
char
*
)
name
;
/* HACK: use "name" as data, to use the mount_single helper */
return
mount_single
(
type
,
flags
,
fakedata
,
sdbfs_fill_super
);
ret
=
mount_single
(
type
,
flags
,
fakedata
,
sdbfs_fill_super
);
printk
(
"%s: %p
\n
"
,
__func__
,
ret
);
return
ret
;
}
static
void
sdbfs_kill_sb
(
struct
super_block
*
sb
)
{
struct
sdbfs_dev
*
sd
=
sb
->
s_fs_info
;
printk
(
"%s
\n
"
,
__func__
);
kill_anon_super
(
sb
);
if
(
sd
)
sdbfs_put
(
sd
);
...
...
@@ -120,6 +297,9 @@ static struct file_system_type sdbfs_fs_type = {
static
int
sdbfs_init
(
void
)
{
sdbfs_inode_cache
=
KMEM_CACHE
(
sdbfs_inode
,
0
);
if
(
!
sdbfs_inode_cache
)
return
-
ENOMEM
;
return
register_filesystem
(
&
sdbfs_fs_type
);
return
0
;
}
...
...
@@ -127,6 +307,7 @@ static int sdbfs_init(void)
static
void
sdbfs_exit
(
void
)
{
unregister_filesystem
(
&
sdbfs_fs_type
);
kmem_cache_destroy
(
sdbfs_inode_cache
);
}
module_init
(
sdbfs_init
);
...
...
sdbfs/kernel/sdbfs-device.c
View file @
7de9a85a
...
...
@@ -49,6 +49,11 @@ int sdbfs_register_device(struct sdbfs_dev *sd)
if
(
!
strcmp
(
osd
->
name
,
sd
->
name
))
return
-
EBUSY
;
list_add
(
&
sd
->
list
,
&
sdbfs_devlist
);
list_for_each_entry
(
osd
,
&
sdbfs_devlist
,
list
)
printk
(
"list entry %p
\n
"
,
osd
);
return
0
;
}
EXPORT_SYMBOL
(
sdbfs_register_device
);
...
...
@@ -57,8 +62,14 @@ void sdbfs_unregister_device(struct sdbfs_dev *sd)
{
struct
sdbfs_dev
*
osd
;
list_for_each_entry
(
osd
,
&
sdbfs_devlist
,
list
)
printk
(
"list entry %p
\n
"
,
osd
);
printk
(
"removing %p
\n
"
,
sd
);
list_for_each_entry
(
osd
,
&
sdbfs_devlist
,
list
)
if
(
osd
==
sd
)
list_del
(
&
sd
->
list
);
break
;
if
(
osd
==
sd
)
list_del
(
&
sd
->
list
);
}
EXPORT_SYMBOL
(
sdbfs_unregister_device
);
sdbfs/kernel/sdbfs-int.h
View file @
7de9a85a
...
...
@@ -9,5 +9,17 @@
*/
#ifndef __SDBFS_INT_H__
#define __SDBFS_INT_H__
#include <linux/fs.h>
#include <linux/sdb.h>
struct
sdbfs_inode
{
union
{
struct
sdb_device
s_d
;
struct
sdb_interconnect
s_i
;
struct
sdb_bridge
s_b
;
};
struct
sdb_device
*
files
;
/* Only used for directories */
struct
inode
ino
;
};
#endif
/* __SDBFS_INT_H__ */
sdbfs/kernel/sdbfs.h
View file @
7de9a85a
...
...
@@ -21,10 +21,10 @@ struct sdbfs_dev;
*/
struct
sdbfs_dev_ops
{
struct
module
*
owner
;
int
(
*
erase
)(
struct
sdbfs_dev
*
d
,
uint32_t
begin
,
uint32_t
end
);
ssize_t
(
*
read
)(
struct
sdbfs_dev
*
d
,
uint32_t
begin
,
u8
*
buf
,
int
(
*
erase
)(
struct
sdbfs_dev
*
s
d
,
uint32_t
begin
,
uint32_t
end
);
ssize_t
(
*
read
)(
struct
sdbfs_dev
*
sd
,
uint32_t
begin
,
void
*
buf
,
size_t
count
);
ssize_t
(
*
write
)(
struct
sdbfs_dev
*
d
,
uint32_t
begin
,
u8
*
buf
,
ssize_t
(
*
write
)(
struct
sdbfs_dev
*
sd
,
uint32_t
begin
,
void
*
buf
,
size_t
count
);
};
...
...
@@ -36,11 +36,11 @@ struct sdbfs_dev {
struct
list_head
list
;
};
/* Internal inter-file calls */
struct
sdbfs_dev
*
sdbfs_get_by_name
(
char
*
name
);
void
sdbfs_put
(
struct
sdbfs_dev
*
sd
);
/* Exported to other modules */
int
sdbfs_register_device
(
struct
sdbfs_dev
*
sd
);
void
sdbfs_unregister_device
(
struct
sdbfs_dev
*
sd
);
...
...
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