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
7403ed3e
Commit
7403ed3e
authored
Jul 02, 2002
by
Paul Mackerras
Browse files
Options
Browse Files
Download
Plain Diff
Merge samba.org:/home/paulus/kernel/linux-2.5
into samba.org:/home/paulus/kernel/for-linus-ppc
parents
738198a4
f9fc1633
Changes
62
Show whitespace changes
Inline
Side-by-side
Showing
62 changed files
with
1443 additions
and
1665 deletions
+1443
-1665
Documentation/filesystems/ntfs.txt
Documentation/filesystems/ntfs.txt
+9
-0
drivers/char/drm/drm.h
drivers/char/drm/drm.h
+7
-99
drivers/char/drm/drm_context.h
drivers/char/drm/drm_context.h
+1
-1
drivers/char/drm/gamma_dma.c
drivers/char/drm/gamma_dma.c
+2
-0
drivers/char/drm/gamma_drm.h
drivers/char/drm/gamma_drm.h
+10
-0
drivers/char/drm/gamma_drv.c
drivers/char/drm/gamma_drv.c
+2
-0
drivers/char/drm/i810_dma.c
drivers/char/drm/i810_dma.c
+2
-0
drivers/char/drm/i810_drm.h
drivers/char/drm/i810_drm.h
+22
-2
drivers/char/drm/i810_drv.c
drivers/char/drm/i810_drv.c
+2
-0
drivers/char/drm/i830_dma.c
drivers/char/drm/i830_dma.c
+3
-6
drivers/char/drm/i830_drm.h
drivers/char/drm/i830_drm.h
+13
-0
drivers/char/drm/i830_drv.c
drivers/char/drm/i830_drv.c
+2
-0
drivers/char/drm/mga_dma.c
drivers/char/drm/mga_dma.c
+2
-0
drivers/char/drm/mga_drm.h
drivers/char/drm/mga_drm.h
+15
-0
drivers/char/drm/mga_drv.c
drivers/char/drm/mga_drv.c
+2
-0
drivers/char/drm/mga_state.c
drivers/char/drm/mga_state.c
+2
-0
drivers/char/drm/mga_warp.c
drivers/char/drm/mga_warp.c
+2
-0
drivers/char/drm/r128_cce.c
drivers/char/drm/r128_cce.c
+2
-0
drivers/char/drm/r128_drm.h
drivers/char/drm/r128_drm.h
+21
-0
drivers/char/drm/r128_drv.c
drivers/char/drm/r128_drv.c
+2
-0
drivers/char/drm/r128_drv.h
drivers/char/drm/r128_drv.h
+10
-39
drivers/char/drm/r128_state.c
drivers/char/drm/r128_state.c
+2
-0
drivers/char/drm/radeon_cp.c
drivers/char/drm/radeon_cp.c
+7
-1
drivers/char/drm/radeon_drm.h
drivers/char/drm/radeon_drm.h
+23
-0
drivers/char/drm/radeon_drv.c
drivers/char/drm/radeon_drv.c
+4
-2
drivers/char/drm/radeon_drv.h
drivers/char/drm/radeon_drv.h
+31
-37
drivers/char/drm/radeon_state.c
drivers/char/drm/radeon_state.c
+17
-6
drivers/char/drm/sis_drm.h
drivers/char/drm/sis_drm.h
+10
-0
drivers/scsi/i60uscsi.c
drivers/scsi/i60uscsi.c
+63
-46
drivers/scsi/i60uscsi.h
drivers/scsi/i60uscsi.h
+0
-567
drivers/scsi/inia100.c
drivers/scsi/inia100.c
+174
-243
drivers/scsi/inia100.h
drivers/scsi/inia100.h
+163
-7
drivers/video/matrox/matroxfb_base.c
drivers/video/matrox/matroxfb_base.c
+14
-1
drivers/video/matrox/matroxfb_crtc2.c
drivers/video/matrox/matroxfb_crtc2.c
+16
-3
fs/binfmt_elf.c
fs/binfmt_elf.c
+4
-8
fs/ntfs/ChangeLog
fs/ntfs/ChangeLog
+66
-7
fs/ntfs/Makefile
fs/ntfs/Makefile
+1
-1
fs/ntfs/aops.c
fs/ntfs/aops.c
+115
-297
fs/ntfs/dir.c
fs/ntfs/dir.c
+1
-1
fs/ntfs/dir.h
fs/ntfs/dir.h
+1
-1
fs/ntfs/inode.c
fs/ntfs/inode.c
+316
-67
fs/ntfs/inode.h
fs/ntfs/inode.h
+115
-18
fs/ntfs/mft.c
fs/ntfs/mft.c
+7
-8
fs/ntfs/namei.c
fs/ntfs/namei.c
+14
-10
fs/ntfs/ntfs.h
fs/ntfs/ntfs.h
+0
-35
fs/ntfs/super.c
fs/ntfs/super.c
+51
-58
fs/ntfs/volume.h
fs/ntfs/volume.h
+5
-12
fs/proc/array.c
fs/proc/array.c
+7
-6
fs/proc/proc_misc.c
fs/proc/proc_misc.c
+1
-1
include/asm-i386/param.h
include/asm-i386/param.h
+6
-4
include/linux/sched.h
include/linux/sched.h
+1
-2
include/linux/time.h
include/linux/time.h
+31
-11
include/linux/times.h
include/linux/times.h
+4
-0
kernel/acct.c
kernel/acct.c
+2
-2
kernel/exit.c
kernel/exit.c
+2
-2
kernel/fork.c
kernel/fork.c
+2
-2
kernel/itimer.c
kernel/itimer.c
+4
-32
kernel/signal.c
kernel/signal.c
+2
-2
kernel/sys.c
kernel/sys.c
+16
-15
kernel/timer.c
kernel/timer.c
+2
-2
mm/oom_kill.c
mm/oom_kill.c
+1
-1
sound/oss/maestro.c
sound/oss/maestro.c
+9
-0
No files found.
Documentation/filesystems/ntfs.txt
View file @
7403ed3e
...
...
@@ -247,6 +247,15 @@ ChangeLog
Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog.
2.0.13:
- Internal changes towards using iget5_locked() in preparation for
fake inodes and small cleanups to ntfs_volume structure.
2.0.12:
- Internal cleanups in address space operations made possible by the
changes introduced in the previous release.
2.0.11:
- Internal updates and cleanups introducing the first step towards
fake inode based attribute i/o.
2.0.10:
- Microsoft says that the maximum number of inodes is 2^32 - 1. Update
the driver accordingly to only use 32-bits to store inode numbers on
...
...
drivers/char/drm/drm.h
View file @
7403ed3e
...
...
@@ -84,6 +84,10 @@ typedef unsigned int drm_magic_t;
/* Warning: If you change this structure, make sure you change
* XF86DRIClipRectRec in the server as well */
/* KW: Actually it's illegal to change either for
* backwards-compatibility reasons.
*/
typedef
struct
drm_clip_rect
{
unsigned
short
x1
;
unsigned
short
y1
;
...
...
@@ -99,15 +103,6 @@ typedef struct drm_tex_region {
unsigned
int
age
;
}
drm_tex_region_t
;
/* Seperate include files for the i810/mga/r128 specific structures */
#include "mga_drm.h"
#include "i810_drm.h"
#include "r128_drm.h"
#include "radeon_drm.h"
#include "sis_drm.h"
#include "i830_drm.h"
#include "gamma_drm.h"
typedef
struct
drm_version
{
int
version_major
;
/* Major version */
int
version_minor
;
/* Minor version */
...
...
@@ -428,95 +423,8 @@ typedef struct drm_scatter_gather {
#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t)
#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t)
/* MGA specific ioctls */
#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x41, drm_lock_t)
#define DRM_IOCTL_MGA_RESET DRM_IO( 0x42)
#define DRM_IOCTL_MGA_SWAP DRM_IO( 0x43)
#define DRM_IOCTL_MGA_CLEAR DRM_IOW( 0x44, drm_mga_clear_t)
#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x45, drm_mga_vertex_t)
#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t)
#define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x47, drm_mga_iload_t)
#define DRM_IOCTL_MGA_BLIT DRM_IOW( 0x48, drm_mga_blit_t)
/* i810 specific ioctls */
#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t)
#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t)
#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t)
#define DRM_IOCTL_I810_FLUSH DRM_IO( 0x43)
#define DRM_IOCTL_I810_GETAGE DRM_IO( 0x44)
#define DRM_IOCTL_I810_GETBUF DRM_IOWR(0x45, drm_i810_dma_t)
#define DRM_IOCTL_I810_SWAP DRM_IO( 0x46)
#define DRM_IOCTL_I810_COPY DRM_IOW( 0x47, drm_i810_copy_t)
#define DRM_IOCTL_I810_DOCOPY DRM_IO( 0x48)
#define DRM_IOCTL_I810_OV0INFO DRM_IOR( 0x49, drm_i810_overlay_t)
#define DRM_IOCTL_I810_FSTATUS DRM_IO ( 0x4a)
#define DRM_IOCTL_I810_OV0FLIP DRM_IO ( 0x4b)
#define DRM_IOCTL_I810_MC DRM_IOW( 0x4c, drm_i810_mc_t)
#define DRM_IOCTL_I810_RSTATUS DRM_IO ( 0x4d )
/* Rage 128 specific ioctls */
#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t)
#define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41)
#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( 0x42, drm_r128_cce_stop_t)
#define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43)
#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44)
#define DRM_IOCTL_R128_RESET DRM_IO( 0x46)
#define DRM_IOCTL_R128_SWAP DRM_IO( 0x47)
#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x48, drm_r128_clear_t)
#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t)
#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t)
#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t)
#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4c, drm_r128_depth_t)
#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t)
#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t)
#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t)
#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( 0x51, drm_r128_clear2_t)
/* Radeon specific ioctls */
#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( 0x40, drm_radeon_init_t)
#define DRM_IOCTL_RADEON_CP_START DRM_IO( 0x41)
#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( 0x42, drm_radeon_cp_stop_t)
#define DRM_IOCTL_RADEON_CP_RESET DRM_IO( 0x43)
#define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( 0x44)
#define DRM_IOCTL_RADEON_RESET DRM_IO( 0x45)
#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( 0x46, drm_radeon_fullscreen_t)
#define DRM_IOCTL_RADEON_SWAP DRM_IO( 0x47)
#define DRM_IOCTL_RADEON_CLEAR DRM_IOW( 0x48, drm_radeon_clear_t)
#define DRM_IOCTL_RADEON_VERTEX DRM_IOW( 0x49, drm_radeon_vertex_t)
#define DRM_IOCTL_RADEON_INDICES DRM_IOW( 0x4a, drm_radeon_indices_t)
#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t)
#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t)
#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t)
#define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( 0x4f, drm_radeon_vertex_t)
#define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( 0x50, drm_radeon_cmd_buffer_t)
#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(0x51, drm_radeon_getparam_t)
#define DRM_IOCTL_RADEON_FLIP DRM_IO( 0x52)
/* Gamma specific ioctls */
#define DRM_IOCTL_GAMMA_INIT DRM_IOW( 0x40, drm_gamma_init_t)
#define DRM_IOCTL_GAMMA_COPY DRM_IOW( 0x41, drm_gamma_copy_t)
/* SiS specific ioctls */
#define SIS_IOCTL_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t)
#define SIS_IOCTL_FB_FREE DRM_IOW( 0x45, drm_sis_mem_t)
#define SIS_IOCTL_AGP_INIT DRM_IOWR(0x53, drm_sis_agp_t)
#define SIS_IOCTL_AGP_ALLOC DRM_IOWR(0x54, drm_sis_mem_t)
#define SIS_IOCTL_AGP_FREE DRM_IOW( 0x55, drm_sis_mem_t)
#define SIS_IOCTL_FLIP DRM_IOW( 0x48, drm_sis_flip_t)
#define SIS_IOCTL_FLIP_INIT DRM_IO( 0x49)
#define SIS_IOCTL_FLIP_FINAL DRM_IO( 0x50)
/* I830 specific ioctls */
#define DRM_IOCTL_I830_INIT DRM_IOW( 0x40, drm_i830_init_t)
#define DRM_IOCTL_I830_VERTEX DRM_IOW( 0x41, drm_i830_vertex_t)
#define DRM_IOCTL_I830_CLEAR DRM_IOW( 0x42, drm_i830_clear_t)
#define DRM_IOCTL_I830_FLUSH DRM_IO ( 0x43)
#define DRM_IOCTL_I830_GETAGE DRM_IO ( 0x44)
#define DRM_IOCTL_I830_GETBUF DRM_IOWR(0x45, drm_i830_dma_t)
#define DRM_IOCTL_I830_SWAP DRM_IO ( 0x46)
#define DRM_IOCTL_I830_COPY DRM_IOW( 0x47, drm_i830_copy_t)
#define DRM_IOCTL_I830_DOCOPY DRM_IO ( 0x48)
/* Device specfic ioctls should only be in their respective headers
* The device specific ioctl range is 0x40 to 0x79. */
#define DRM_COMMAND_BASE 0x40
#endif
drivers/char/drm/drm_context.h
View file @
7403ed3e
...
...
@@ -555,7 +555,7 @@ static int DRM(alloc_queue)(drm_device_t *dev)
/* Allocate a new queue */
down
(
&
dev
->
struct_sem
);
queue
=
gamma_alloc
(
sizeof
(
*
queue
),
DRM_MEM_QUEUES
);
queue
=
DRM
(
alloc
)
(
sizeof
(
*
queue
),
DRM_MEM_QUEUES
);
memset
(
queue
,
0
,
sizeof
(
*
queue
));
atomic_set
(
&
queue
->
use_count
,
1
);
...
...
drivers/char/drm/gamma_dma.c
View file @
7403ed3e
...
...
@@ -32,6 +32,8 @@
#define __NO_VERSION__
#include "gamma.h"
#include "drmP.h"
#include "drm.h"
#include "gamma_drm.h"
#include "gamma_drv.h"
#include <linux/interrupt.h>
/* For task queue support */
...
...
drivers/char/drm/gamma_drm.h
View file @
7403ed3e
...
...
@@ -48,6 +48,16 @@ typedef struct _drm_gamma_sarea {
int
vertex_prim
;
}
drm_gamma_sarea_t
;
/* WARNING: If you change any of these defines, make sure to change the
* defines in the Xserver file (xf86drmGamma.h)
*/
/* Gamma specific ioctls
* The device specific ioctl range is 0x40 to 0x79.
*/
#define DRM_IOCTL_GAMMA_INIT DRM_IOW( 0x40, drm_gamma_init_t)
#define DRM_IOCTL_GAMMA_COPY DRM_IOW( 0x41, drm_gamma_copy_t)
typedef
struct
drm_gamma_copy
{
unsigned
int
DMAOutputAddress
;
unsigned
int
DMAOutputCount
;
...
...
drivers/char/drm/gamma_drv.c
View file @
7403ed3e
...
...
@@ -32,6 +32,8 @@
#include <linux/config.h>
#include "gamma.h"
#include "drmP.h"
#include "drm.h"
#include "gamma_drm.h"
#include "gamma_drv.h"
#define DRIVER_AUTHOR "VA Linux Systems Inc."
...
...
drivers/char/drm/i810_dma.c
View file @
7403ed3e
...
...
@@ -33,6 +33,8 @@
#define __NO_VERSION__
#include "i810.h"
#include "drmP.h"
#include "drm.h"
#include "i810_drm.h"
#include "i810_drv.h"
#include <linux/interrupt.h>
/* For task queue support */
#include <linux/delay.h>
...
...
drivers/char/drm/i810_drm.h
View file @
7403ed3e
...
...
@@ -168,14 +168,34 @@ typedef struct _drm_i810_sarea {
}
drm_i810_sarea_t
;
/* WARNING: If you change any of these defines, make sure to change the
* defines in the Xserver file (xf86drmMga.h)
*/
/* i810 specific ioctls
* The device specific ioctl range is 0x40 to 0x79.
*/
#define DRM_IOCTL_I810_INIT DRM_IOW( 0x40, drm_i810_init_t)
#define DRM_IOCTL_I810_VERTEX DRM_IOW( 0x41, drm_i810_vertex_t)
#define DRM_IOCTL_I810_CLEAR DRM_IOW( 0x42, drm_i810_clear_t)
#define DRM_IOCTL_I810_FLUSH DRM_IO( 0x43)
#define DRM_IOCTL_I810_GETAGE DRM_IO( 0x44)
#define DRM_IOCTL_I810_GETBUF DRM_IOWR(0x45, drm_i810_dma_t)
#define DRM_IOCTL_I810_SWAP DRM_IO( 0x46)
#define DRM_IOCTL_I810_COPY DRM_IOW( 0x47, drm_i810_copy_t)
#define DRM_IOCTL_I810_DOCOPY DRM_IO( 0x48)
#define DRM_IOCTL_I810_OV0INFO DRM_IOR( 0x49, drm_i810_overlay_t)
#define DRM_IOCTL_I810_FSTATUS DRM_IO ( 0x4a)
#define DRM_IOCTL_I810_OV0FLIP DRM_IO ( 0x4b)
#define DRM_IOCTL_I810_MC DRM_IOW( 0x4c, drm_i810_mc_t)
#define DRM_IOCTL_I810_RSTATUS DRM_IO ( 0x4d )
typedef
struct
_drm_i810_clear
{
int
clear_color
;
int
clear_depth
;
int
flags
;
}
drm_i810_clear_t
;
/* These may be placeholders if we have more cliprects than
* I810_NR_SAREA_CLIPRECTS. In that case, the client sets discard to
* false, indicating that the buffer will be dispatched again with a
...
...
drivers/char/drm/i810_drv.c
View file @
7403ed3e
...
...
@@ -33,6 +33,8 @@
#include <linux/config.h>
#include "i810.h"
#include "drmP.h"
#include "drm.h"
#include "i810_drm.h"
#include "i810_drv.h"
#define DRIVER_AUTHOR "VA Linux Systems Inc."
...
...
drivers/char/drm/i830_dma.c
View file @
7403ed3e
...
...
@@ -34,10 +34,11 @@
#define __NO_VERSION__
#include "i830.h"
#include "drmP.h"
#include "drm.h"
#include "i830_drm.h"
#include "i830_drv.h"
#include <linux/interrupt.h>
/* For task queue support */
#include <linux/delay.h>
#include <linux/pagemap.h>
/* in case we don't have a 2.3.99-pre6 kernel or later: */
#ifndef VM_DONTCOPY
...
...
@@ -58,7 +59,6 @@
do { \
int _head; \
int _tail; \
int _i; \
do { \
_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR; \
_tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR; \
...
...
@@ -370,8 +370,6 @@ static int i830_wait_ring(drm_device_t *dev, int n)
end
=
jiffies
+
(
HZ
*
3
);
while
(
ring
->
space
<
n
)
{
int
i
;
ring
->
head
=
I830_READ
(
LP_RING
+
RING_HEAD
)
&
HEAD_ADDR
;
ring
->
space
=
ring
->
head
-
(
ring
->
tail
+
8
);
if
(
ring
->
space
<
0
)
ring
->
space
+=
ring
->
Size
;
...
...
@@ -387,7 +385,6 @@ static int i830_wait_ring(drm_device_t *dev, int n)
DRM_ERROR
(
"lockup
\n
"
);
goto
out_wait_ring
;
}
udelay
(
1
);
}
...
...
drivers/char/drm/i830_drm.h
View file @
7403ed3e
...
...
@@ -201,6 +201,19 @@ typedef struct _drm_i830_sarea {
int
vertex_prim
;
}
drm_i830_sarea_t
;
/* I830 specific ioctls
* The device specific ioctl range is 0x40 to 0x79.
*/
#define DRM_IOCTL_I830_INIT DRM_IOW( 0x40, drm_i830_init_t)
#define DRM_IOCTL_I830_VERTEX DRM_IOW( 0x41, drm_i830_vertex_t)
#define DRM_IOCTL_I830_CLEAR DRM_IOW( 0x42, drm_i830_clear_t)
#define DRM_IOCTL_I830_FLUSH DRM_IO ( 0x43)
#define DRM_IOCTL_I830_GETAGE DRM_IO ( 0x44)
#define DRM_IOCTL_I830_GETBUF DRM_IOWR(0x45, drm_i830_dma_t)
#define DRM_IOCTL_I830_SWAP DRM_IO ( 0x46)
#define DRM_IOCTL_I830_COPY DRM_IOW( 0x47, drm_i830_copy_t)
#define DRM_IOCTL_I830_DOCOPY DRM_IO ( 0x48)
typedef
struct
_drm_i830_clear
{
int
clear_color
;
int
clear_depth
;
...
...
drivers/char/drm/i830_drv.c
View file @
7403ed3e
...
...
@@ -34,6 +34,8 @@
#include <linux/config.h>
#include "i830.h"
#include "drmP.h"
#include "drm.h"
#include "i830_drm.h"
#include "i830_drv.h"
#define DRIVER_AUTHOR "VA Linux Systems Inc."
...
...
drivers/char/drm/mga_dma.c
View file @
7403ed3e
...
...
@@ -36,6 +36,8 @@
#define __NO_VERSION__
#include "mga.h"
#include "drmP.h"
#include "drm.h"
#include "mga_drm.h"
#include "mga_drv.h"
#include <linux/interrupt.h>
/* For task queue support */
...
...
drivers/char/drm/mga_drm.h
View file @
7403ed3e
...
...
@@ -38,6 +38,7 @@
/* WARNING: If you change any of these defines, make sure to change the
* defines in the Xserver file (mga_sarea.h)
*/
#ifndef __MGA_SAREA_DEFINES__
#define __MGA_SAREA_DEFINES__
...
...
@@ -225,6 +226,20 @@ typedef struct _drm_mga_sarea {
/* WARNING: If you change any of these defines, make sure to change the
* defines in the Xserver file (xf86drmMga.h)
*/
/* MGA specific ioctls
* The device specific ioctl range is 0x40 to 0x79.
*/
#define DRM_IOCTL_MGA_INIT DRM_IOW( 0x40, drm_mga_init_t)
#define DRM_IOCTL_MGA_FLUSH DRM_IOW( 0x41, drm_lock_t)
#define DRM_IOCTL_MGA_RESET DRM_IO( 0x42)
#define DRM_IOCTL_MGA_SWAP DRM_IO( 0x43)
#define DRM_IOCTL_MGA_CLEAR DRM_IOW( 0x44, drm_mga_clear_t)
#define DRM_IOCTL_MGA_VERTEX DRM_IOW( 0x45, drm_mga_vertex_t)
#define DRM_IOCTL_MGA_INDICES DRM_IOW( 0x46, drm_mga_indices_t)
#define DRM_IOCTL_MGA_ILOAD DRM_IOW( 0x47, drm_mga_iload_t)
#define DRM_IOCTL_MGA_BLIT DRM_IOW( 0x48, drm_mga_blit_t)
typedef
struct
_drm_mga_warp_index
{
int
installed
;
unsigned
long
phys_addr
;
...
...
drivers/char/drm/mga_drv.c
View file @
7403ed3e
...
...
@@ -32,6 +32,8 @@
#include <linux/config.h>
#include "mga.h"
#include "drmP.h"
#include "drm.h"
#include "mga_drm.h"
#include "mga_drv.h"
#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc."
...
...
drivers/char/drm/mga_state.c
View file @
7403ed3e
...
...
@@ -35,6 +35,8 @@
#define __NO_VERSION__
#include "mga.h"
#include "drmP.h"
#include "drm.h"
#include "mga_drm.h"
#include "mga_drv.h"
#include "drm.h"
...
...
drivers/char/drm/mga_warp.c
View file @
7403ed3e
...
...
@@ -30,6 +30,8 @@
#define __NO_VERSION__
#include "mga.h"
#include "drmP.h"
#include "drm.h"
#include "mga_drm.h"
#include "mga_drv.h"
#include "mga_ucode.h"
...
...
drivers/char/drm/r128_cce.c
View file @
7403ed3e
...
...
@@ -31,6 +31,8 @@
#define __NO_VERSION__
#include "r128.h"
#include "drmP.h"
#include "drm.h"
#include "r128_drm.h"
#include "r128_drv.h"
#include <linux/interrupt.h>
/* For task queue support */
...
...
drivers/char/drm/r128_drm.h
View file @
7403ed3e
...
...
@@ -170,6 +170,27 @@ typedef struct drm_r128_sarea {
/* WARNING: If you change any of these defines, make sure to change the
* defines in the Xserver file (xf86drmR128.h)
*/
/* Rage 128 specific ioctls
* The device specific ioctl range is 0x40 to 0x79.
*/
#define DRM_IOCTL_R128_INIT DRM_IOW( 0x40, drm_r128_init_t)
#define DRM_IOCTL_R128_CCE_START DRM_IO( 0x41)
#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( 0x42, drm_r128_cce_stop_t)
#define DRM_IOCTL_R128_CCE_RESET DRM_IO( 0x43)
#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( 0x44)
#define DRM_IOCTL_R128_RESET DRM_IO( 0x46)
#define DRM_IOCTL_R128_SWAP DRM_IO( 0x47)
#define DRM_IOCTL_R128_CLEAR DRM_IOW( 0x48, drm_r128_clear_t)
#define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t)
#define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t)
#define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t)
#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4c, drm_r128_depth_t)
#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t)
#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(0x4f, drm_r128_indirect_t)
#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( 0x50, drm_r128_fullscreen_t)
#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( 0x51, drm_r128_clear2_t)
typedef
struct
drm_r128_init
{
enum
{
R128_INIT_CCE
=
0x01
,
...
...
drivers/char/drm/r128_drv.c
View file @
7403ed3e
...
...
@@ -32,6 +32,8 @@
#include <linux/config.h>
#include "r128.h"
#include "drmP.h"
#include "drm.h"
#include "r128_drm.h"
#include "r128_drv.h"
#include "ati_pcigart.h"
...
...
drivers/char/drm/r128_drv.h
View file @
7403ed3e
...
...
@@ -34,8 +34,8 @@
#ifndef __R128_DRV_H__
#define __R128_DRV_H__
#define GET_RING_HEAD(
ring ) le32_to_cpu( *
(ring)->head )
#define SET_RING_HEAD(
ring, val ) *(ring)->head = cpu_to_le32( val
)
#define GET_RING_HEAD(
ring) readl( (volatile u32 *)
(ring)->head )
#define SET_RING_HEAD(
ring,val) writel( (val), (volatile u32 *) (ring)->head
)
typedef
struct
drm_r128_freelist
{
unsigned
int
age
;
...
...
@@ -384,44 +384,11 @@ extern int r128_cce_indirect( struct inode *inode, struct file *filp,
#define R128_BASE(reg) ((unsigned long)(dev_priv->mmio->handle))
#define R128_ADDR(reg) (R128_BASE( reg ) + reg)
#define R128_DEREF(reg) *(volatile u32 *)R128_ADDR( reg )
#ifdef __alpha__
#define R128_READ(reg) (_R128_READ((u32 *)R128_ADDR(reg)))
static
inline
u32
_R128_READ
(
u32
*
addr
)
{
mb
();
return
*
(
volatile
u32
*
)
addr
;
}
#define R128_WRITE(reg,val) \
do { \
wmb(); \
R128_DEREF(reg) = val; \
} while (0)
#else
#define R128_READ(reg) le32_to_cpu( R128_DEREF( reg ) )
#define R128_WRITE(reg,val) \
do { \
R128_DEREF( reg ) = cpu_to_le32( val ); \
} while (0)
#endif
#define R128_READ(reg) readl( (volatile u32 *) R128_ADDR(reg) )
#define R128_WRITE(reg,val) writel( (val), (volatile u32 *) R128_ADDR(reg) )
#define R128_DEREF8(reg) *(volatile u8 *)R128_ADDR( reg )
#ifdef __alpha__
#define R128_READ8(reg) _R128_READ8((u8 *)R128_ADDR(reg))
static
inline
u8
_R128_READ8
(
u8
*
addr
)
{
mb
();
return
*
(
volatile
u8
*
)
addr
;
}
#define R128_WRITE8(reg,val) \
do { \
wmb(); \
R128_DEREF8(reg) = val; \
} while (0)
#else
#define R128_READ8(reg) R128_DEREF8( reg )
#define R128_WRITE8(reg,val) do { R128_DEREF8( reg ) = val; } while (0)
#endif
#define R128_READ8(reg) readb( (volatile u8 *) R128_ADDR(reg) )
#define R128_WRITE8(reg,val) writeb( (val), (volatile u8 *) R128_ADDR(reg) )
#define R128_WRITE_PLL(addr,val) \
do { \
...
...
@@ -493,7 +460,11 @@ do { \
* Ring control
*/
#if defined(__powerpc__)
#define r128_flush_write_combine() (void) GET_RING_HEAD( &dev_priv->ring )
#else
#define r128_flush_write_combine() mb()
#endif
#define R128_VERBOSE 0
...
...
drivers/char/drm/r128_state.c
View file @
7403ed3e
...
...
@@ -30,6 +30,8 @@
#define __NO_VERSION__
#include "r128.h"
#include "drmP.h"
#include "drm.h"
#include "r128_drm.h"
#include "r128_drv.h"
#include "drm.h"
#include <linux/delay.h>
...
...
drivers/char/drm/radeon_cp.c
View file @
7403ed3e
...
...
@@ -31,6 +31,8 @@
#define __NO_VERSION__
#include "radeon.h"
#include "drmP.h"
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
#include <linux/interrupt.h>
/* For task queue support */
...
...
@@ -38,7 +40,7 @@
#define RADEON_FIFO_DEBUG 0
#if defined(__alpha__)
#if defined(__alpha__)
|| defined(__powerpc__)
# define PCIGART_ENABLED
#else
# undef PCIGART_ENABLED
...
...
@@ -631,7 +633,11 @@ static void radeon_cp_init_ring_buffer( drm_device_t *dev,
}
/* Set ring buffer size */
#ifdef __BIG_ENDIAN
RADEON_WRITE
(
RADEON_CP_RB_CNTL
,
dev_priv
->
ring
.
size_l2qw
|
RADEON_BUF_SWAP_32BIT
);
#else
RADEON_WRITE
(
RADEON_CP_RB_CNTL
,
dev_priv
->
ring
.
size_l2qw
);
#endif
radeon_do_wait_for_idle
(
dev_priv
);
...
...
drivers/char/drm/radeon_drm.h
View file @
7403ed3e
...
...
@@ -301,6 +301,29 @@ typedef struct {
*
* KW: actually it's illegal to change any of this (backwards compatibility).
*/
/* Radeon specific ioctls
* The device specific ioctl range is 0x40 to 0x79.
*/
#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( 0x40, drm_radeon_init_t)
#define DRM_IOCTL_RADEON_CP_START DRM_IO( 0x41)
#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( 0x42, drm_radeon_cp_stop_t)
#define DRM_IOCTL_RADEON_CP_RESET DRM_IO( 0x43)
#define DRM_IOCTL_RADEON_CP_IDLE DRM_IO( 0x44)
#define DRM_IOCTL_RADEON_RESET DRM_IO( 0x45)
#define DRM_IOCTL_RADEON_FULLSCREEN DRM_IOW( 0x46, drm_radeon_fullscreen_t)
#define DRM_IOCTL_RADEON_SWAP DRM_IO( 0x47)
#define DRM_IOCTL_RADEON_CLEAR DRM_IOW( 0x48, drm_radeon_clear_t)
#define DRM_IOCTL_RADEON_VERTEX DRM_IOW( 0x49, drm_radeon_vertex_t)
#define DRM_IOCTL_RADEON_INDICES DRM_IOW( 0x4a, drm_radeon_indices_t)
#define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t)
#define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t)
#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4e, drm_radeon_texture_t)
#define DRM_IOCTL_RADEON_VERTEX2 DRM_IOW( 0x4f, drm_radeon_vertex_t)
#define DRM_IOCTL_RADEON_CMDBUF DRM_IOW( 0x50, drm_radeon_cmd_buffer_t)
#define DRM_IOCTL_RADEON_GETPARAM DRM_IOWR(0x51, drm_radeon_getparam_t)
#define DRM_IOCTL_RADEON_FLIP DRM_IO( 0x52)
typedef
struct
drm_radeon_init
{
enum
{
RADEON_INIT_CP
=
0x01
,
...
...
drivers/char/drm/radeon_drv.c
View file @
7403ed3e
...
...
@@ -30,6 +30,8 @@
#include <linux/config.h>
#include "radeon.h"
#include "drmP.h"
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
#include "ati_pcigart.h"
...
...
@@ -37,11 +39,11 @@
#define DRIVER_NAME "radeon"
#define DRIVER_DESC "ATI Radeon"
#define DRIVER_DATE "20020
52
1"
#define DRIVER_DATE "20020
61
1"
#define DRIVER_MAJOR 1
#define DRIVER_MINOR 3
#define DRIVER_PATCHLEVEL
0
#define DRIVER_PATCHLEVEL
1
/* Interface history:
*
...
...
drivers/char/drm/radeon_drv.h
View file @
7403ed3e
...
...
@@ -31,6 +31,9 @@
#ifndef __RADEON_DRV_H__
#define __RADEON_DRV_H__
#define GET_RING_HEAD(ring) readl( (volatile u32 *) (ring)->head )
#define SET_RING_HEAD(ring,val) writel( (val), (volatile u32 *) (ring)->head )
typedef
struct
drm_radeon_freelist
{
unsigned
int
age
;
drm_buf_t
*
buf
;
...
...
@@ -141,7 +144,7 @@ extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
static
inline
void
radeon_update_ring_snapshot
(
drm_radeon_ring_buffer_t
*
ring
)
{
ring
->
space
=
(
*
(
volatile
int
*
)
ring
->
head
-
ring
->
tail
)
*
sizeof
(
u32
);
ring
->
space
=
(
GET_RING_HEAD
(
ring
)
-
ring
->
tail
)
*
sizeof
(
u32
);
if
(
ring
->
space
<=
0
)
ring
->
space
+=
ring
->
size
;
}
...
...
@@ -249,6 +252,12 @@ extern int radeon_cp_flip( struct inode *inode, struct file *filp,
# define RADEON_ISYNC_WAIT_IDLEGUI (1 << 4)
# define RADEON_ISYNC_CPSCRATCH_IDLEGUI (1 << 5)
#define RADEON_RBBM_GUICNTL 0x172c
# define RADEON_HOST_DATA_SWAP_NONE (0 << 0)
# define RADEON_HOST_DATA_SWAP_16BIT (1 << 0)
# define RADEON_HOST_DATA_SWAP_32BIT (2 << 0)
# define RADEON_HOST_DATA_SWAP_HDW (3 << 0)
#define RADEON_MC_AGP_LOCATION 0x014c
#define RADEON_MC_FB_LOCATION 0x0148
#define RADEON_MCLK_CNTL 0x0012
...
...
@@ -424,6 +433,7 @@ extern int radeon_cp_flip( struct inode *inode, struct file *filp,
#define RADEON_CP_RB_BASE 0x0700
#define RADEON_CP_RB_CNTL 0x0704
# define RADEON_BUF_SWAP_32BIT (2 << 16)
#define RADEON_CP_RB_RPTR_ADDR 0x070c
#define RADEON_CP_RB_RPTR 0x0710
#define RADEON_CP_RB_WPTR 0x0714
...
...
@@ -533,41 +543,11 @@ extern int radeon_cp_flip( struct inode *inode, struct file *filp,
#define RADEON_BASE(reg) ((unsigned long)(dev_priv->mmio->handle))
#define RADEON_ADDR(reg) (RADEON_BASE( reg ) + reg)
#define RADEON_DEREF(reg) *(volatile u32 *)RADEON_ADDR( reg )
#ifdef __alpha__
#define RADEON_READ(reg) (_RADEON_READ((u32 *)RADEON_ADDR( reg )))
static
inline
u32
_RADEON_READ
(
u32
*
addr
)
{
mb
();
return
*
(
volatile
u32
*
)
addr
;
}
#define RADEON_WRITE(reg,val) \
do { \
wmb(); \
RADEON_DEREF(reg) = val; \
} while (0)
#else
#define RADEON_READ(reg) RADEON_DEREF( reg )
#define RADEON_WRITE(reg, val) do { RADEON_DEREF( reg ) = val; } while (0)
#endif
#define RADEON_READ(reg) readl( (volatile u32 *) RADEON_ADDR(reg) )
#define RADEON_WRITE(reg,val) writel( (val), (volatile u32 *) RADEON_ADDR(reg) )
#define RADEON_DEREF8(reg) *(volatile u8 *)RADEON_ADDR( reg )
#ifdef __alpha__
#define RADEON_READ8(reg) _RADEON_READ8((u8 *)RADEON_ADDR( reg ))
static
inline
u8
_RADEON_READ8
(
u8
*
addr
)
{
mb
();
return
*
(
volatile
u8
*
)
addr
;
}
#define RADEON_WRITE8(reg,val) \
do { \
wmb(); \
RADEON_DEREF8( reg ) = val; \
} while (0)
#else
#define RADEON_READ8(reg) RADEON_DEREF8( reg )
#define RADEON_WRITE8(reg, val) do { RADEON_DEREF8( reg ) = val; } while (0)
#endif
#define RADEON_READ8(reg) readb( (volatile u8 *) RADEON_ADDR(reg) )
#define RADEON_WRITE8(reg,val) writeb( (val), (volatile u8 *) RADEON_ADDR(reg) )
#define RADEON_WRITE_PLL( addr, val ) \
do { \
...
...
@@ -664,6 +644,15 @@ do { \
goto __ring_space_done; \
udelay( 1 ); \
} \
DRM_ERROR( "ring space check from memory failed, reading register...\n" ); \
/* If ring space check fails from RAM, try reading the \
register directly */
\
ring->space = 4 * ( RADEON_READ( RADEON_CP_RB_RPTR ) - ring->tail ); \
if ( ring->space <= 0 ) \
ring->space += ring->size; \
if ( ring->space >= ring->high_mark ) \
goto __ring_space_done; \
\
DRM_ERROR( "ring space check failed!\n" ); \
return -EBUSY; \
} \
...
...
@@ -701,7 +690,11 @@ do { \
* Ring control
*/
#if defined(__powerpc__)
#define radeon_flush_write_combine() (void) GET_RING_HEAD( &dev_priv->ring )
#else
#define radeon_flush_write_combine() mb()
#endif
#define RADEON_VERBOSE 0
...
...
@@ -738,6 +731,7 @@ do { \
} while (0)
#define COMMIT_RING() do { \
radeon_flush_write_combine(); \
RADEON_WRITE( RADEON_CP_RB_WPTR, dev_priv->ring.tail ); \
} while (0)
...
...
drivers/char/drm/radeon_state.c
View file @
7403ed3e
...
...
@@ -30,8 +30,9 @@
#define __NO_VERSION__
#include "radeon.h"
#include "drmP.h"
#include "radeon_drv.h"
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
#include <linux/delay.h>
...
...
@@ -669,7 +670,6 @@ static void radeon_cp_dispatch_vertex( drm_device_t *dev,
int
i
=
0
;
RING_LOCALS
;
DRM_DEBUG
(
"%s: hwprim 0x%x vfmt 0x%x %d..%d %d verts
\n
"
,
__FUNCTION__
,
prim
->
prim
,
...
...
@@ -684,7 +684,6 @@ static void radeon_cp_dispatch_vertex( drm_device_t *dev,
return
;
}
do
{
/* Emit the next cliprect */
if
(
i
<
nbox
)
{
...
...
@@ -906,6 +905,16 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev,
ADVANCE_RING
();
#ifdef __BIG_ENDIAN
/* The Mesa texture functions provide the data in little endian as the
* chip wants it, but we need to compensate for the fact that the CP
* ring gets byte-swapped
*/
BEGIN_RING
(
2
);
OUT_RING_REG
(
RADEON_RBBM_GUICNTL
,
RADEON_HOST_DATA_SWAP_32BIT
);
ADVANCE_RING
();
#endif
/* Make a copy of the parameters in case we have to update them
* for a multi-pass texture blit.
*/
...
...
@@ -1081,6 +1090,7 @@ static int radeon_do_init_pageflip( drm_device_t *dev )
dev_priv
->
page_flipping
=
1
;
dev_priv
->
current_page
=
0
;
dev_priv
->
sarea_priv
->
pfCurrentPage
=
dev_priv
->
current_page
;
return
0
;
}
...
...
@@ -1095,6 +1105,7 @@ int radeon_do_cleanup_pageflip( drm_device_t *dev )
dev_priv
->
page_flipping
=
0
;
dev_priv
->
current_page
=
0
;
dev_priv
->
sarea_priv
->
pfCurrentPage
=
dev_priv
->
current_page
;
return
0
;
}
...
...
@@ -1585,15 +1596,15 @@ static int radeon_emit_packets(
drm_radeon_cmd_header_t
header
,
drm_radeon_cmd_buffer_t
*
cmdbuf
)
{
int
sz
=
packet
[(
int
)
header
.
packet
.
packet_id
].
len
;
int
reg
=
packet
[(
int
)
header
.
packet
.
packet_id
].
start
;
int
id
=
(
int
)
header
.
packet
.
packet_id
;
int
sz
=
packet
[
id
].
len
;
int
reg
=
packet
[
id
].
start
;
int
*
data
=
(
int
*
)
cmdbuf
->
buf
;
RING_LOCALS
;
if
(
sz
*
sizeof
(
int
)
>
cmdbuf
->
bufsz
)
return
-
EINVAL
;
BEGIN_RING
(
sz
+
1
);
OUT_RING
(
CP_PACKET0
(
reg
,
(
sz
-
1
)
)
);
OUT_RING_USER_TABLE
(
data
,
sz
);
...
...
drivers/char/drm/sis_drm.h
View file @
7403ed3e
...
...
@@ -2,6 +2,16 @@
#ifndef _sis_drm_public_h_
#define _sis_drm_public_h_
/* SiS specific ioctls */
#define SIS_IOCTL_FB_ALLOC DRM_IOWR(0x44, drm_sis_mem_t)
#define SIS_IOCTL_FB_FREE DRM_IOW( 0x45, drm_sis_mem_t)
#define SIS_IOCTL_AGP_INIT DRM_IOWR(0x53, drm_sis_agp_t)
#define SIS_IOCTL_AGP_ALLOC DRM_IOWR(0x54, drm_sis_mem_t)
#define SIS_IOCTL_AGP_FREE DRM_IOW( 0x55, drm_sis_mem_t)
#define SIS_IOCTL_FLIP DRM_IOW( 0x48, drm_sis_flip_t)
#define SIS_IOCTL_FLIP_INIT DRM_IO( 0x49)
#define SIS_IOCTL_FLIP_FINAL DRM_IO( 0x50)
typedef
struct
{
int
context
;
unsigned
int
offset
;
...
...
drivers/scsi/i60uscsi.c
View file @
7403ed3e
...
...
@@ -66,12 +66,24 @@
* 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up
* 01/31/99 bv - v1.02b Use mdelay instead of waitForPause
* 08/08/99 bv - v1.02c Use waitForPause again.
* 06/25/02 Doug Ledford <dledford@redhat.com> - v1.02d
* - Remove limit on number of controllers
* - Port to DMA mapping API
* - Clean up interrupt handler registration
* - Fix memory leaks
* - Fix allocation of scsi host structs and private data
**************************************************************************/
#include <linux/version.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <asm/irq.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <asm/io.h>
#include "i60uscsi.h"
#include <linux/blkdev.h>
#include "scsi.h"
#include "hosts.h"
#include "inia100.h"
#define JIFFIES_TO_MS(t) ((t) * 1000 / HZ)
#define MS_TO_JIFFIES(j) ((j * HZ) / 1000)
...
...
@@ -98,10 +110,7 @@ ORC_SCB *orc_alloc_scb(ORC_HCS * hcsp);
extern
void
inia100SCBPost
(
BYTE
*
pHcb
,
BYTE
*
pScb
);
/* ---- INTERNAL VARIABLES ---- */
ORC_HCS
orc_hcs
[
MAX_SUPPORTED_ADAPTERS
];
static
INIA100_ADPT_STRUCT
inia100_adpt
[
MAX_SUPPORTED_ADAPTERS
];
/* set by inia100_setup according to the command line */
int
orc_num_scb
;
struct
inia100_Adpt_Struc
*
inia100_adpt
;
NVRAM
nvram
,
*
nvramp
=
&
nvram
;
static
UCHAR
dftNvRam
[
64
]
=
...
...
@@ -300,7 +309,7 @@ UCHAR get_NVRAM(ORC_HCS * hcsp, unsigned char address, unsigned char *pDataIn)
/***************************************************************************/
void
orc_exec_scb
(
ORC_HCS
*
hcsp
,
ORC_SCB
*
scbp
)
{
scbp
->
SCB_Status
=
SCB_POST
;
scbp
->
SCB_Status
=
ORC
SCB_POST
;
ORC_WR
(
hcsp
->
HCS_Base
+
ORC_PQUEUE
,
scbp
->
SCB_ScbIdx
);
return
;
}
...
...
@@ -439,17 +448,11 @@ void setup_SCBs(ORC_HCS * hcsp)
{
ORC_SCB
*
pVirScb
;
int
i
;
UCHAR
j
;
ESCB
*
pVirEscb
;
PVOID
pPhysEscb
;
PVOID
tPhysEscb
;
dma_addr_t
pPhysEscb
;
j
=
0
;
pVirScb
=
NULL
;
tPhysEscb
=
(
PVOID
)
NULL
;
pPhysEscb
=
(
PVOID
)
NULL
;
/* Setup SCB HCS_Base and SCB Size registers */
ORC_WR
(
hcsp
->
HCS_Base
+
ORC_SCBSIZE
,
orc_num_scb
);
/* Total number of SCBs */
ORC_WR
(
hcsp
->
HCS_Base
+
ORC_SCBSIZE
,
ORC_MAXQUEUE
);
/* Total number of SCBs */
/* SCB HCS_Base address 0 */
ORC_WRLONG
(
hcsp
->
HCS_Base
+
ORC_SCBBASE0
,
hcsp
->
HCS_physScbArray
);
/* SCB HCS_Base address 1 */
...
...
@@ -459,8 +462,8 @@ void setup_SCBs(ORC_HCS * hcsp)
pVirScb
=
(
ORC_SCB
*
)
hcsp
->
HCS_virScbArray
;
pVirEscb
=
(
ESCB
*
)
hcsp
->
HCS_virEscbArray
;
for
(
i
=
0
;
i
<
orc_num_scb
;
i
++
)
{
pPhysEscb
=
(
PVOID
)
(
hcsp
->
HCS_physEscbArray
+
(
sizeof
(
ESCB
)
*
i
));
for
(
i
=
0
;
i
<
ORC_MAXQUEUE
;
i
++
)
{
pPhysEscb
=
(
hcsp
->
HCS_physEscbArray
+
(
sizeof
(
ESCB
)
*
i
));
pVirScb
->
SCB_SGPAddr
=
(
U32
)
pPhysEscb
;
pVirScb
->
SCB_SensePAddr
=
(
U32
)
pPhysEscb
;
pVirScb
->
SCB_EScb
=
pVirEscb
;
...
...
@@ -534,7 +537,7 @@ int init_orchid(ORC_HCS * hcsp)
readBytep
=
(
UCHAR
*
)
&
(
nvramp
->
Target00Config
);
for
(
i
=
0
;
i
<
16
;
readBytep
++
,
i
++
)
{
hcsp
->
TargetFlag
[
i
]
=
*
readBytep
;
hcsp
->
MaximumTags
[
i
]
=
orc_num_scb
;
hcsp
->
MaximumTags
[
i
]
=
ORC_MAXTAGS
;
}
/* for */
if
(
nvramp
->
SCSI0Config
&
NCC_BUSRESET
)
{
/* Reset SCSI bus */
...
...
@@ -578,7 +581,7 @@ int orc_reset_scsi_bus(ORC_HCS * pHCB)
Output : None.
Return : pSRB - Pointer to SCSI request block.
*****************************************************************************/
int
orc_device_reset
(
ORC_HCS
*
pHCB
,
ULONG
SCpnt
,
unsigned
int
target
,
unsigned
int
ResetFlags
)
int
orc_device_reset
(
ORC_HCS
*
pHCB
,
Scsi_Cmnd
*
SCpnt
,
unsigned
int
target
,
unsigned
int
ResetFlags
)
{
/* I need Host Control Block Information */
ORC_SCB
*
pScb
;
ESCB
*
pVirEscb
;
...
...
@@ -595,14 +598,14 @@ int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned
initAFlag
(
pHCB
);
/* device reset */
for
(
i
=
0
;
i
<
orc_num_scb
;
i
++
)
{
for
(
i
=
0
;
i
<
ORC_MAXQUEUE
;
i
++
)
{
pVirEscb
=
pVirScb
->
SCB_EScb
;
if
((
pVirScb
->
SCB_Status
)
&&
(
pVirEscb
->
SCB_Srb
==
(
unsigned
char
*
)
SCpnt
))
if
((
pVirScb
->
SCB_Status
)
&&
(
pVirEscb
->
SCB_Srb
==
SCpnt
))
break
;
pVirScb
++
;
}
if
(
i
==
orc_num_scb
)
{
if
(
i
==
ORC_MAXQUEUE
)
{
printk
(
"Unable to Reset - No SCB Found
\n
"
);
spin_unlock_irqrestore
(
&
(
pHCB
->
BitAllocFlagLock
),
flags
);
return
(
SCSI_RESET_NOT_RUNNING
);
...
...
@@ -624,7 +627,7 @@ int orc_device_reset(ORC_HCS * pHCB, ULONG SCpnt, unsigned int target, unsigned
pVirEscb
->
SCB_Srb
=
0
;
if
(
ResetFlags
&
SCSI_RESET_SYNCHRONOUS
)
{
pVirEscb
->
SCB_Srb
=
(
unsigned
char
*
)
SCpnt
;
pVirEscb
->
SCB_Srb
=
SCpnt
;
}
orc_exec_scb
(
pHCB
,
pScb
);
/* Start execute SCB */
spin_unlock_irqrestore
(
&
(
pHCB
->
BitAllocFlagLock
),
flags
);
...
...
@@ -640,7 +643,6 @@ ORC_SCB *__orc_alloc_scb(ORC_HCS * hcsp)
ULONG
idx
;
UCHAR
index
;
UCHAR
i
;
ULONG
flags
;
Ch
=
hcsp
->
HCS_Index
;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
...
...
@@ -687,6 +689,22 @@ void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
}
/***************************************************************************/
void
orc_release_dma
(
ORC_HCS
*
hcsp
,
Scsi_Cmnd
*
SCpnt
)
{
struct
scatterlist
*
pSrbSG
;
if
(
SCpnt
->
use_sg
)
{
pSrbSG
=
(
struct
scatterlist
*
)
SCpnt
->
request_buffer
;
pci_unmap_sg
(
hcsp
->
pdev
,
pSrbSG
,
SCpnt
->
use_sg
,
scsi_to_pci_dma_dir
(
SCpnt
->
sc_data_direction
));
}
else
if
(
SCpnt
->
request_bufflen
!=
0
)
{
pci_unmap_single
(
hcsp
->
pdev
,
(
U32
)
SCpnt
->
host_scribble
,
SCpnt
->
request_bufflen
,
scsi_to_pci_dma_dir
(
SCpnt
->
sc_data_direction
));
}
}
/*****************************************************************************
Function name : Addinia100_into_Adapter_table
Description : This function will scan PCI bus to get all Orchid card
...
...
@@ -695,33 +713,29 @@ void orc_release_scb(ORC_HCS * hcsp, ORC_SCB * scbp)
Return : SUCCESSFUL - Successful scan
ohterwise - No drives founded
*****************************************************************************/
int
Addinia100_into_Adapter_table
(
WORD
wBIOS
,
WORD
wBASE
,
BYTE
bInterrupt
,
BYTE
bBus
,
BYTE
bDevice
)
int
Addinia100_into_Adapter_table
(
WORD
wBIOS
,
WORD
wBASE
,
struct
pci_dev
*
pdev
,
int
iAdapters
)
{
unsigned
int
i
,
j
;
for
(
i
=
0
;
i
<
MAX_SUPPORTED_ADAPTERS
;
i
++
)
{
for
(
i
=
0
;
i
<
iAdapters
;
i
++
)
{
if
(
inia100_adpt
[
i
].
ADPT_BIOS
<
wBIOS
)
continue
;
if
(
inia100_adpt
[
i
].
ADPT_BIOS
==
wBIOS
)
{
if
(
inia100_adpt
[
i
].
ADPT_BASE
==
wBASE
)
{
if
(
inia100_adpt
[
i
].
ADPT_
Bus
!=
0xFF
)
if
(
inia100_adpt
[
i
].
ADPT_
pdev
->
bus
->
number
!=
0xFF
)
return
(
FAILURE
);
}
else
if
(
inia100_adpt
[
i
].
ADPT_BASE
<
wBASE
)
continue
;
}
for
(
j
=
MAX_SUPPORTED_ADAPTERS
-
1
;
j
>
i
;
j
--
)
{
for
(
j
=
iAdapters
-
1
;
j
>
i
;
j
--
)
{
inia100_adpt
[
j
].
ADPT_BASE
=
inia100_adpt
[
j
-
1
].
ADPT_BASE
;
inia100_adpt
[
j
].
ADPT_INTR
=
inia100_adpt
[
j
-
1
].
ADPT_INTR
;
inia100_adpt
[
j
].
ADPT_BIOS
=
inia100_adpt
[
j
-
1
].
ADPT_BIOS
;
inia100_adpt
[
j
].
ADPT_Bus
=
inia100_adpt
[
j
-
1
].
ADPT_Bus
;
inia100_adpt
[
j
].
ADPT_Device
=
inia100_adpt
[
j
-
1
].
ADPT_Device
;
inia100_adpt
[
j
].
ADPT_pdev
=
inia100_adpt
[
j
-
1
].
ADPT_pdev
;
}
inia100_adpt
[
i
].
ADPT_BASE
=
wBASE
;
inia100_adpt
[
i
].
ADPT_INTR
=
bInterrupt
;
inia100_adpt
[
i
].
ADPT_BIOS
=
wBIOS
;
inia100_adpt
[
i
].
ADPT_Bus
=
bBus
;
inia100_adpt
[
i
].
ADPT_Device
=
bDevice
;
inia100_adpt
[
i
].
ADPT_pdev
=
pdev
;
return
(
SUCCESSFUL
);
}
return
(
FAILURE
);
...
...
@@ -733,20 +747,23 @@ int Addinia100_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
Description : This function will scan PCI bus to get all Orchid card
Input : None.
Output : None.
Return : SUCCESSFUL - Successful scan
ohterwise - No drives founded
Return : 0 on success, 1 on failure
*****************************************************************************/
void
init_inia100Adapter_table
(
void
)
int
init_inia100Adapter_table
(
int
iAdapters
)
{
int
i
;
for
(
i
=
0
;
i
<
MAX_SUPPORTED_ADAPTERS
;
i
++
)
{
/* Initialize adapter structure */
inia100_adpt
=
kmalloc
(
sizeof
(
INIA100_ADPT_STRUCT
)
*
iAdapters
,
GFP_KERNEL
);
if
(
inia100_adpt
==
NULL
)
return
1
;
for
(
i
=
0
;
i
<
iAdapters
;
i
++
)
{
/* Initialize adapter structure */
inia100_adpt
[
i
].
ADPT_BIOS
=
0xffff
;
inia100_adpt
[
i
].
ADPT_BASE
=
0xffff
;
inia100_adpt
[
i
].
ADPT_INTR
=
0xff
;
inia100_adpt
[
i
].
ADPT_Bus
=
0xff
;
inia100_adpt
[
i
].
ADPT_Device
=
0xff
;
inia100_adpt
[
i
].
ADPT_pdev
=
NULL
;
}
return
0
;
}
/*****************************************************************************
...
...
@@ -760,7 +777,7 @@ void get_orcPCIConfig(ORC_HCS * pCurHcb, int ch_idx)
{
pCurHcb
->
HCS_Base
=
inia100_adpt
[
ch_idx
].
ADPT_BASE
;
/* Supply base address */
pCurHcb
->
HCS_BIOS
=
inia100_adpt
[
ch_idx
].
ADPT_BIOS
;
/* Supply BIOS address */
pCurHcb
->
HCS_Intr
=
inia100_adpt
[
ch_idx
].
ADPT_
INTR
;
/* Supply interrupt line */
pCurHcb
->
HCS_Intr
=
inia100_adpt
[
ch_idx
].
ADPT_
pdev
->
irq
;
/* Supply interrupt line */
return
;
}
...
...
@@ -805,7 +822,7 @@ int abort_SCB(ORC_HCS * hcsp, ORC_SCB * pScb)
Output : None.
Return : pSRB - Pointer to SCSI request block.
*****************************************************************************/
int
orc_abort_srb
(
ORC_HCS
*
hcsp
,
ULONG
SCpnt
)
int
orc_abort_srb
(
ORC_HCS
*
hcsp
,
Scsi_Cmnd
*
SCpnt
)
{
ESCB
*
pVirEscb
;
ORC_SCB
*
pVirScb
;
...
...
@@ -816,9 +833,9 @@ int orc_abort_srb(ORC_HCS * hcsp, ULONG SCpnt)
pVirScb
=
(
ORC_SCB
*
)
hcsp
->
HCS_virScbArray
;
for
(
i
=
0
;
i
<
orc_num_scb
;
i
++
,
pVirScb
++
)
{
for
(
i
=
0
;
i
<
ORC_MAXQUEUE
;
i
++
,
pVirScb
++
)
{
pVirEscb
=
pVirScb
->
SCB_EScb
;
if
((
pVirScb
->
SCB_Status
)
&&
(
pVirEscb
->
SCB_Srb
==
(
unsigned
char
*
)
SCpnt
))
{
if
((
pVirScb
->
SCB_Status
)
&&
(
pVirEscb
->
SCB_Srb
==
SCpnt
))
{
if
(
pVirScb
->
SCB_TagMsg
==
0
)
{
spin_unlock_irqrestore
(
&
(
hcsp
->
BitAllocFlagLock
),
flags
);
return
(
SCSI_ABORT_BUSY
);
...
...
drivers/scsi/i60uscsi.h
deleted
100644 → 0
View file @
738198a4
/**************************************************************************
* Initio A100 device driver for Linux.
*
* Copyright (c) 1994-1998 Initio Corporation
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
* --------------------------------------------------------------------------
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification, immediately at the beginning of the file.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* Where this Software is combined with software released under the terms of
* the GNU General Public License ("GPL") and the terms of the GPL would require the
* combined work to also be released under the terms of the GPL, the terms
* and conditions of this License will apply in addition to those of the
* GPL with the exception of any terms or conditions of this License that
* conflict with, or are expressly prohibited by, the GPL.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
**************************************************************************
*
* Module: inia100.h
* Description: INI-A100U2W LINUX device driver header
* Revision History:
* 06/18/98 HL, Initial Version 1.02
* 12/19/98 bv, v1.02a Use spinlocks for 2.1.95 and up.
**************************************************************************/
#include <linux/config.h>
#include <linux/types.h>
#define ULONG unsigned long
#define PVOID void *
#define USHORT unsigned short
#define UCHAR unsigned char
#define BYTE unsigned char
#define WORD unsigned short
#define DWORD unsigned long
#define UBYTE unsigned char
#define UWORD unsigned short
#define UDWORD unsigned long
#define U32 u32
#ifndef NULL
#define NULL 0
/* zero */
#endif
#ifndef TRUE
#define TRUE (1)
/* boolean true */
#endif
#ifndef FALSE
#define FALSE (0)
/* boolean false */
#endif
#ifndef FAILURE
#define FAILURE (-1)
#endif
#if 1
#define ORC_MAXQUEUE 245
#else
#define ORC_MAXQUEUE 25
#endif
#define TOTAL_SG_ENTRY 32
#define MAX_TARGETS 16
#define IMAX_CDB 15
#define SENSE_SIZE 14
#define MAX_SUPPORTED_ADAPTERS 4
#define SUCCESSFUL 0x00
#define I920_DEVICE_ID 0x0002
/* Initio's inic-950 product ID */
/************************************************************************/
/* Scatter-Gather Element Structure */
/************************************************************************/
typedef
struct
ORC_SG_Struc
{
U32
SG_Ptr
;
/* Data Pointer */
U32
SG_Len
;
/* Data Length */
}
ORC_SG
;
typedef
struct
inia100_Adpt_Struc
{
UWORD
ADPT_BIOS
;
/* 0 */
UWORD
ADPT_BASE
;
/* 1 */
UBYTE
ADPT_Bus
;
/* 2 */
UBYTE
ADPT_Device
;
/* 3 */
UBYTE
ADPT_INTR
;
/* 4 */
}
INIA100_ADPT_STRUCT
;
/* SCSI related definition */
#define DISC_NOT_ALLOW 0x80
/* Disconnect is not allowed */
#define DISC_ALLOW 0xC0
/* Disconnect is allowed */
#define ORC_OFFSET_SCB 16
#define ORC_MAX_SCBS 250
#define MAX_CHANNELS 2
#define MAX_ESCB_ELE 64
#define TCF_DRV_255_63 0x0400
/********************************************************/
/* Orchid Configuration Register Set */
/********************************************************/
#define ORC_PVID 0x00
/* Vendor ID */
#define ORC_VENDOR_ID 0x1101
/* Orchid vendor ID */
#define ORC_PDID 0x02
/* Device ID */
#define ORC_DEVICE_ID 0x1060
/* Orchid device ID */
#define ORC_COMMAND 0x04
/* Command */
#define BUSMS 0x04
/* BUS MASTER Enable */
#define IOSPA 0x01
/* IO Space Enable */
#define ORC_STATUS 0x06
/* Status register */
#define ORC_REVISION 0x08
/* Revision number */
#define ORC_BASE 0x10
/* Base address */
#define ORC_BIOS 0x50
/* Expansion ROM base address */
#define ORC_INT_NUM 0x3C
/* Interrupt line */
#define ORC_INT_PIN 0x3D
/* Interrupt pin */
/********************************************************/
/* Orchid Host Command Set */
/********************************************************/
#define ORC_CMD_NOP 0x00
/* Host command - NOP */
#define ORC_CMD_VERSION 0x01
/* Host command - Get F/W version */
#define ORC_CMD_ECHO 0x02
/* Host command - ECHO */
#define ORC_CMD_SET_NVM 0x03
/* Host command - Set NVRAM */
#define ORC_CMD_GET_NVM 0x04
/* Host command - Get NVRAM */
#define ORC_CMD_GET_BUS_STATUS 0x05
/* Host command - Get SCSI bus status */
#define ORC_CMD_ABORT_SCB 0x06
/* Host command - Abort SCB */
#define ORC_CMD_ISSUE_SCB 0x07
/* Host command - Issue SCB */
/********************************************************/
/* Orchid Register Set */
/********************************************************/
#define ORC_GINTS 0xA0
/* Global Interrupt Status */
#define QINT 0x04
/* Reply Queue Interrupt */
#define ORC_GIMSK 0xA1
/* Global Interrupt MASK */
#define MQINT 0x04
/* Mask Reply Queue Interrupt */
#define ORC_GCFG 0xA2
/* Global Configure */
#define EEPRG 0x01
/* Enable EEPROM programming */
#define ORC_GSTAT 0xA3
/* Global status */
#define WIDEBUS 0x10
/* Wide SCSI Devices connected */
#define ORC_HDATA 0xA4
/* Host Data */
#define ORC_HCTRL 0xA5
/* Host Control */
#define SCSIRST 0x80
/* SCSI bus reset */
#define HDO 0x40
/* Host data out */
#define HOSTSTOP 0x02
/* Host stop RISC engine */
#define DEVRST 0x01
/* Device reset */
#define ORC_HSTUS 0xA6
/* Host Status */
#define HDI 0x02
/* Host data in */
#define RREADY 0x01
/* RISC engine is ready to receive */
#define ORC_NVRAM 0xA7
/* Nvram port address */
#define SE2CS 0x008
#define SE2CLK 0x004
#define SE2DO 0x002
#define SE2DI 0x001
#define ORC_PQUEUE 0xA8
/* Posting queue FIFO */
#define ORC_PQCNT 0xA9
/* Posting queue FIFO Cnt */
#define ORC_RQUEUE 0xAA
/* Reply queue FIFO */
#define ORC_RQUEUECNT 0xAB
/* Reply queue FIFO Cnt */
#define ORC_FWBASEADR 0xAC
/* Firmware base address */
#define ORC_EBIOSADR0 0xB0
/* External Bios address */
#define ORC_EBIOSADR1 0xB1
/* External Bios address */
#define ORC_EBIOSADR2 0xB2
/* External Bios address */
#define ORC_EBIOSDATA 0xB3
/* External Bios address */
#define ORC_SCBSIZE 0xB7
/* SCB size register */
#define ORC_SCBBASE0 0xB8
/* SCB base address 0 */
#define ORC_SCBBASE1 0xBC
/* SCB base address 1 */
#define ORC_RISCCTL 0xE0
/* RISC Control */
#define PRGMRST 0x002
#define DOWNLOAD 0x001
#define ORC_PRGMCTR0 0xE2
/* RISC program counter */
#define ORC_PRGMCTR1 0xE3
/* RISC program counter */
#define ORC_RISCRAM 0xEC
/* RISC RAM data port 4 bytes */
typedef
struct
orc_extended_scb
{
/* Extended SCB */
ORC_SG
ESCB_SGList
[
TOTAL_SG_ENTRY
];
/*0 Start of SG list */
unsigned
char
*
SCB_Srb
;
/*50 SRB Pointer */
// Scsi_Cmnd *SCB_Srb; /*50 SRB Pointer */
}
ESCB
;
/***********************************************************************
SCSI Control Block
************************************************************************/
typedef
struct
orc_scb
{
/* Scsi_Ctrl_Blk */
UBYTE
SCB_Opcode
;
/*00 SCB command code&residual */
UBYTE
SCB_Flags
;
/*01 SCB Flags */
UBYTE
SCB_Target
;
/*02 Target Id */
UBYTE
SCB_Lun
;
/*03 Lun */
U32
SCB_Reserved0
;
/*04 Reserved for ORCHID must 0 */
U32
SCB_XferLen
;
/*08 Data Transfer Length */
U32
SCB_Reserved1
;
/*0C Reserved for ORCHID must 0 */
U32
SCB_SGLen
;
/*10 SG list # * 8 */
U32
SCB_SGPAddr
;
/*14 SG List Buf physical Addr */
U32
SCB_SGPAddrHigh
;
/*18 SG Buffer high physical Addr */
UBYTE
SCB_HaStat
;
/*1C Host Status */
UBYTE
SCB_TaStat
;
/*1D Target Status */
UBYTE
SCB_Status
;
/*1E SCB status */
UBYTE
SCB_Link
;
/*1F Link pointer, default 0xFF */
UBYTE
SCB_SenseLen
;
/*20 Sense Allocation Length */
UBYTE
SCB_CDBLen
;
/*21 CDB Length */
UBYTE
SCB_Ident
;
/*22 Identify */
UBYTE
SCB_TagMsg
;
/*23 Tag Message */
UBYTE
SCB_CDB
[
IMAX_CDB
];
/*24 SCSI CDBs */
UBYTE
SCB_ScbIdx
;
/*3C Index for this ORCSCB */
U32
SCB_SensePAddr
;
/*34 Sense Buffer physical Addr */
ESCB
*
SCB_EScb
;
/*38 Extended SCB Pointer */
#ifndef ALPHA
UBYTE
SCB_Reserved2
[
4
];
/*3E Reserved for Driver use */
#endif
}
ORC_SCB
;
/* Opcodes of ORCSCB_Opcode */
#define ORC_EXECSCSI 0x00
/* SCSI initiator command with residual */
#define ORC_BUSDEVRST 0x01
/* SCSI Bus Device Reset */
/* Status of ORCSCB_Status */
#define SCB_COMPLETE 0x00
/* SCB request completed */
#define SCB_POST 0x01
/* SCB is posted by the HOST */
/* Bit Definition for ORCSCB_Flags */
#define SCF_DISINT 0x01
/* Disable HOST interrupt */
#define SCF_DIR 0x18
/* Direction bits */
#define SCF_NO_DCHK 0x00
/* Direction determined by SCSI */
#define SCF_DIN 0x08
/* From Target to Initiator */
#define SCF_DOUT 0x10
/* From Initiator to Target */
#define SCF_NO_XF 0x18
/* No data transfer */
#define SCF_POLL 0x40
/* Error Codes for ORCSCB_HaStat */
#define HOST_SEL_TOUT 0x11
#define HOST_DO_DU 0x12
#define HOST_BUS_FREE 0x13
#define HOST_BAD_PHAS 0x14
#define HOST_INV_CMD 0x16
#define HOST_SCSI_RST 0x1B
#define HOST_DEV_RST 0x1C
/* Error Codes for ORCSCB_TaStat */
#define TARGET_CHK_COND 0x02
#define TARGET_BUSY 0x08
#define TARGET_TAG_FULL 0x28
/* Queue tag msg: Simple_quque_tag, Head_of_queue_tag, Ordered_queue_tag */
#define MSG_STAG 0x20
#define MSG_HTAG 0x21
#define MSG_OTAG 0x22
#define MSG_IGNOREWIDE 0x23
#define MSG_IDENT 0x80
#define MSG_DISC 0x40
/* Disconnect allowed */
/* SCSI MESSAGE */
#define MSG_EXTEND 0x01
#define MSG_SDP 0x02
#define MSG_ABORT 0x06
#define MSG_REJ 0x07
#define MSG_NOP 0x08
#define MSG_PARITY 0x09
#define MSG_DEVRST 0x0C
#define MSG_STAG 0x20
/***********************************************************************
Target Device Control Structure
**********************************************************************/
typedef
struct
ORC_Tar_Ctrl_Struc
{
UBYTE
TCS_DrvDASD
;
/* 6 */
UBYTE
TCS_DrvSCSI
;
/* 7 */
UBYTE
TCS_DrvHead
;
/* 8 */
UWORD
TCS_DrvFlags
;
/* 4 */
UBYTE
TCS_DrvSector
;
/* 7 */
}
ORC_TCS
,
*
PORC_TCS
;
/* Bit Definition for TCF_DrvFlags */
#define TCS_DF_NODASD_SUPT 0x20
/* Suppress OS/2 DASD Mgr support */
#define TCS_DF_NOSCSI_SUPT 0x40
/* Suppress OS/2 SCSI Mgr support */
/***********************************************************************
Host Adapter Control Structure
************************************************************************/
typedef
struct
ORC_Ha_Ctrl_Struc
{
USHORT
HCS_Base
;
/* 00 */
UBYTE
HCS_Index
;
/* 02 */
UBYTE
HCS_Intr
;
/* 04 */
UBYTE
HCS_SCSI_ID
;
/* 06 H/A SCSI ID */
UBYTE
HCS_BIOS
;
/* 07 BIOS configuration */
UBYTE
HCS_Flags
;
/* 0B */
UBYTE
HCS_HAConfig1
;
/* 1B SCSI0MAXTags */
UBYTE
HCS_MaxTar
;
/* 1B SCSI0MAXTags */
USHORT
HCS_Units
;
/* Number of units this adapter */
USHORT
HCS_AFlags
;
/* Adapter info. defined flags */
ULONG
HCS_Timeout
;
/* Adapter timeout value */
PVOID
HCS_virScbArray
;
/* 28 Virtual Pointer to SCB array */
U32
HCS_physScbArray
;
/* Scb Physical address */
PVOID
HCS_virEscbArray
;
/* Virtual pointer to ESCB Scatter list */
U32
HCS_physEscbArray
;
/* scatter list Physical address */
UBYTE
TargetFlag
[
16
];
/* 30 target configuration, TCF_EN_TAG */
UBYTE
MaximumTags
[
16
];
/* 40 ORC_MAX_SCBS */
UBYTE
ActiveTags
[
16
][
16
];
/* 50 */
ORC_TCS
HCS_Tcs
[
16
];
/* 28 */
U32
BitAllocFlag
[
MAX_CHANNELS
][
8
];
/* Max STB is 256, So 256/32 */
spinlock_t
BitAllocFlagLock
;
ULONG
pSRB_head
;
ULONG
pSRB_tail
;
spinlock_t
pSRB_lock
;
}
ORC_HCS
;
/* Bit Definition for HCS_Flags */
#define HCF_SCSI_RESET 0x01
/* SCSI BUS RESET */
#define HCF_PARITY 0x02
/* parity card */
#define HCF_LVDS 0x10
/* parity card */
/* Bit Definition for TargetFlag */
#define TCF_EN_255 0x08
#define TCF_EN_TAG 0x10
#define TCF_BUSY 0x20
#define TCF_DISCONNECT 0x40
#define TCF_SPIN_UP 0x80
/* Bit Definition for HCS_AFlags */
#define HCS_AF_IGNORE 0x01
/* Adapter ignore */
#define HCS_AF_DISABLE_RESET 0x10
/* Adapter disable reset */
#define HCS_AF_DISABLE_ADPT 0x80
/* Adapter disable */
/*---------------------------------------*/
/* TimeOut for RESET to complete (30s) */
/* */
/* After a RESET the drive is checked */
/* every 200ms. */
/*---------------------------------------*/
#define DELAYED_RESET_MAX (30*1000L)
#define DELAYED_RESET_INTERVAL 200L
/*----------------------------------------------*/
/* TimeOut for IRQ from last interrupt (5s) */
/*----------------------------------------------*/
#define IRQ_TIMEOUT_INTERVAL (5*1000L)
/*----------------------------------------------*/
/* Retry Delay interval (200ms) */
/*----------------------------------------------*/
#define DELAYED_RETRY_INTERVAL 200L
#define INQUIRY_SIZE 36
#define CAPACITY_SIZE 8
#define DEFAULT_SENSE_LEN 14
#define DEVICE_NOT_FOUND 0x86
/*----------------------------------------------*/
/* Definition for PCI device */
/*----------------------------------------------*/
#define MAX_PCI_DEVICES 21
#define MAX_PCI_BUSES 8
typedef
struct
Adpt_Struc
{
USHORT
ADPT_BIOS
;
/* 0 */
UBYTE
ADPT_BASE
;
/* 1 */
UBYTE
ADPT_Bus
;
/* 2 */
UBYTE
ADPT_Device
;
/* 3 */
UBYTE
ADPT_Reserved
[
3
];
}
JACS
,
*
PJACS
;
typedef
struct
_NVRAM
{
/*----------header ---------------*/
UCHAR
SubVendorID0
;
/* 00 - Sub Vendor ID */
UCHAR
SubVendorID1
;
/* 00 - Sub Vendor ID */
UCHAR
SubSysID0
;
/* 02 - Sub System ID */
UCHAR
SubSysID1
;
/* 02 - Sub System ID */
UCHAR
SubClass
;
/* 04 - Sub Class */
UCHAR
VendorID0
;
/* 05 - Vendor ID */
UCHAR
VendorID1
;
/* 05 - Vendor ID */
UCHAR
DeviceID0
;
/* 07 - Device ID */
UCHAR
DeviceID1
;
/* 07 - Device ID */
UCHAR
Reserved0
[
2
];
/* 09 - Reserved */
UCHAR
Revision
;
/* 0B - Revision of data structure */
/* ----Host Adapter Structure ---- */
UCHAR
NumOfCh
;
/* 0C - Number of SCSI channel */
UCHAR
BIOSConfig1
;
/* 0D - BIOS configuration 1 */
UCHAR
BIOSConfig2
;
/* 0E - BIOS boot channel&target ID */
UCHAR
BIOSConfig3
;
/* 0F - BIOS configuration 3 */
/* ----SCSI channel Structure ---- */
/* from "CTRL-I SCSI Host Adapter SetUp menu " */
UCHAR
SCSI0Id
;
/* 10 - Channel 0 SCSI ID */
UCHAR
SCSI0Config
;
/* 11 - Channel 0 SCSI configuration */
UCHAR
SCSI0MaxTags
;
/* 12 - Channel 0 Maximum tags */
UCHAR
SCSI0ResetTime
;
/* 13 - Channel 0 Reset recovering time */
UCHAR
ReservedforChannel0
[
2
];
/* 14 - Reserved */
/* ----SCSI target Structure ---- */
/* from "CTRL-I SCSI device SetUp menu " */
UCHAR
Target00Config
;
/* 16 - Channel 0 Target 0 config */
UCHAR
Target01Config
;
/* 17 - Channel 0 Target 1 config */
UCHAR
Target02Config
;
/* 18 - Channel 0 Target 2 config */
UCHAR
Target03Config
;
/* 19 - Channel 0 Target 3 config */
UCHAR
Target04Config
;
/* 1A - Channel 0 Target 4 config */
UCHAR
Target05Config
;
/* 1B - Channel 0 Target 5 config */
UCHAR
Target06Config
;
/* 1C - Channel 0 Target 6 config */
UCHAR
Target07Config
;
/* 1D - Channel 0 Target 7 config */
UCHAR
Target08Config
;
/* 1E - Channel 0 Target 8 config */
UCHAR
Target09Config
;
/* 1F - Channel 0 Target 9 config */
UCHAR
Target0AConfig
;
/* 20 - Channel 0 Target A config */
UCHAR
Target0BConfig
;
/* 21 - Channel 0 Target B config */
UCHAR
Target0CConfig
;
/* 22 - Channel 0 Target C config */
UCHAR
Target0DConfig
;
/* 23 - Channel 0 Target D config */
UCHAR
Target0EConfig
;
/* 24 - Channel 0 Target E config */
UCHAR
Target0FConfig
;
/* 25 - Channel 0 Target F config */
UCHAR
SCSI1Id
;
/* 26 - Channel 1 SCSI ID */
UCHAR
SCSI1Config
;
/* 27 - Channel 1 SCSI configuration */
UCHAR
SCSI1MaxTags
;
/* 28 - Channel 1 Maximum tags */
UCHAR
SCSI1ResetTime
;
/* 29 - Channel 1 Reset recovering time */
UCHAR
ReservedforChannel1
[
2
];
/* 2A - Reserved */
/* ----SCSI target Structure ---- */
/* from "CTRL-I SCSI device SetUp menu " */
UCHAR
Target10Config
;
/* 2C - Channel 1 Target 0 config */
UCHAR
Target11Config
;
/* 2D - Channel 1 Target 1 config */
UCHAR
Target12Config
;
/* 2E - Channel 1 Target 2 config */
UCHAR
Target13Config
;
/* 2F - Channel 1 Target 3 config */
UCHAR
Target14Config
;
/* 30 - Channel 1 Target 4 config */
UCHAR
Target15Config
;
/* 31 - Channel 1 Target 5 config */
UCHAR
Target16Config
;
/* 32 - Channel 1 Target 6 config */
UCHAR
Target17Config
;
/* 33 - Channel 1 Target 7 config */
UCHAR
Target18Config
;
/* 34 - Channel 1 Target 8 config */
UCHAR
Target19Config
;
/* 35 - Channel 1 Target 9 config */
UCHAR
Target1AConfig
;
/* 36 - Channel 1 Target A config */
UCHAR
Target1BConfig
;
/* 37 - Channel 1 Target B config */
UCHAR
Target1CConfig
;
/* 38 - Channel 1 Target C config */
UCHAR
Target1DConfig
;
/* 39 - Channel 1 Target D config */
UCHAR
Target1EConfig
;
/* 3A - Channel 1 Target E config */
UCHAR
Target1FConfig
;
/* 3B - Channel 1 Target F config */
UCHAR
reserved
[
3
];
/* 3C - Reserved */
/* ---------- CheckSum ---------- */
UCHAR
CheckSum
;
/* 3F - Checksum of NVRam */
}
NVRAM
,
*
PNVRAM
;
/* Bios Configuration for nvram->BIOSConfig1 */
#define NBC_BIOSENABLE 0x01
/* BIOS enable */
#define NBC_CDROM 0x02
/* Support bootable CDROM */
#define NBC_REMOVABLE 0x04
/* Support removable drive */
/* Bios Configuration for nvram->BIOSConfig2 */
#define NBB_TARGET_MASK 0x0F
/* Boot SCSI target ID number */
#define NBB_CHANL_MASK 0xF0
/* Boot SCSI channel number */
/* Bit definition for nvram->SCSIConfig */
#define NCC_BUSRESET 0x01
/* Reset SCSI bus at power up */
#define NCC_PARITYCHK 0x02
/* SCSI parity enable */
#define NCC_LVDS 0x10
/* Enable LVDS */
#define NCC_ACTTERM1 0x20
/* Enable active terminator 1 */
#define NCC_ACTTERM2 0x40
/* Enable active terminator 2 */
#define NCC_AUTOTERM 0x80
/* Enable auto termination */
/* Bit definition for nvram->TargetxConfig */
#define NTC_PERIOD 0x07
/* Maximum Sync. Speed */
#define NTC_1GIGA 0x08
/* 255 head / 63 sectors (64/32) */
#define NTC_NO_SYNC 0x10
/* NO SYNC. NEGO */
#define NTC_NO_WIDESYNC 0x20
/* NO WIDE SYNC. NEGO */
#define NTC_DISC_ENABLE 0x40
/* Enable SCSI disconnect */
#define NTC_SPINUP 0x80
/* Start disk drive */
/* Default NVRam values */
#define NBC_DEFAULT (NBC_ENABLE)
#define NCC_DEFAULT (NCC_BUSRESET | NCC_AUTOTERM | NCC_PARITYCHK)
#define NCC_MAX_TAGS 0x20
/* Maximum tags per target */
#define NCC_RESET_TIME 0x0A
/* SCSI RESET recovering time */
#define NTC_DEFAULT (NTC_1GIGA | NTC_NO_WIDESYNC | NTC_DISC_ENABLE)
typedef
union
{
/* Union define for mechanism 1 */
struct
{
unsigned
char
RegNum
;
unsigned
char
FcnNum
:
3
;
unsigned
char
DeviceNum
:
5
;
unsigned
char
BusNum
;
unsigned
char
Reserved
:
7
;
unsigned
char
Enable
:
1
;
}
sConfigAdr
;
unsigned
long
lConfigAdr
;
}
CONFIG_ADR
;
typedef
union
{
/* Union define for mechanism 2 */
struct
{
unsigned
char
RegNum
;
unsigned
char
DeviceNum
;
unsigned
short
Reserved
;
}
sHostAdr
;
unsigned
long
lHostAdr
;
}
HOST_ADR
;
#define ORC_RD(x,y) (UCHAR)(inb( (int)((ULONG)((ULONG)x+(UCHAR)y)) ))
#define ORC_RDLONG(x,y) (long)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
#define ORC_WR( adr,data) outb( (UCHAR)(data), (int)(adr))
#define ORC_WRSHORT(adr,data) outw( (UWORD)(data), (int)(adr))
#define ORC_WRLONG( adr,data) outl( (ULONG)(data), (int)(adr))
#define SCSI_ABORT_SNOOZE 0
#define SCSI_ABORT_SUCCESS 1
#define SCSI_ABORT_PENDING 2
#define SCSI_ABORT_BUSY 3
#define SCSI_ABORT_NOT_RUNNING 4
#define SCSI_ABORT_ERROR 5
#define SCSI_RESET_SNOOZE 0
#define SCSI_RESET_PUNT 1
#define SCSI_RESET_SUCCESS 2
#define SCSI_RESET_PENDING 3
#define SCSI_RESET_WAKEUP 4
#define SCSI_RESET_NOT_RUNNING 5
#define SCSI_RESET_ERROR 6
#define SCSI_RESET_SYNCHRONOUS 0x01
#define SCSI_RESET_ASYNCHRONOUS 0x02
#define SCSI_RESET_SUGGEST_BUS_RESET 0x04
#define SCSI_RESET_SUGGEST_HOST_RESET 0x08
#define SCSI_RESET_BUS_RESET 0x100
#define SCSI_RESET_HOST_RESET 0x200
#define SCSI_RESET_ACTION 0xff
drivers/scsi/inia100.c
View file @
7403ed3e
...
...
@@ -59,6 +59,12 @@
* adapters
* 09/24/98 hl - v1.02 initial production release.
* 12/19/98 bv - v1.02a Use spinlocks for 2.1.95 and up.
* 06/25/02 Doug Ledford <dledford@redhat.com> - v1.02d
* - Remove limit on number of controllers
* - Port to DMA mapping API
* - Clean up interrupt handler registration
* - Fix memory leaks
* - Fix allocation of scsi host structs and private data
**************************************************************************/
#define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S)
...
...
@@ -67,11 +73,8 @@
#include <linux/version.h>
#endif
#error Please convert me to Documentation/DMA-mapping.txt
#include <linux/module.h>
#include <stdarg.h>
#include <asm/irq.h>
#include <linux/errno.h>
#include <linux/delay.h>
...
...
@@ -100,44 +103,34 @@ static Scsi_Host_Template driver_template = INIA100;
char
*
inia100_Copyright
=
"Copyright (C) 1998-99"
;
char
*
inia100_InitioName
=
"by Initio Corporation"
;
char
*
inia100_ProductName
=
"INI-A100U2W"
;
char
*
inia100_Version
=
"v1.02
c
"
;
char
*
inia100_Version
=
"v1.02
d
"
;
/* set by inia100_setup according to the command line */
static
int
setup_called
=
0
;
static
int
orc_num_ch
=
MAX_SUPPORTED_ADAPTERS
;
/* Maximum 4 adapters */
/* ---- INTERNAL VARIABLES ---- */
#define NUMBER(arr) (sizeof(arr) / sizeof(arr[0]))
static
char
*
setup_str
=
(
char
*
)
NULL
;
static
void
inia100_intr0
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
);
static
void
inia100_intr1
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
);
static
void
inia100_intr2
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
);
static
void
inia100_intr3
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
);
static
void
inia100_intr4
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
);
static
void
inia100_intr5
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
);
static
void
inia100_intr6
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
);
static
void
inia100_intr7
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
);
static
void
inia100_intr
(
int
,
void
*
,
struct
pt_regs
*
);
static
void
inia100_panic
(
char
*
msg
);
void
inia100SCBPost
(
BYTE
*
pHcb
,
BYTE
*
pScb
);
/* ---- EXTERNAL VARIABLES ---- */
extern
int
Addinia100_into_Adapter_table
(
WORD
,
WORD
,
BYTE
,
BYTE
,
BYTE
);
extern
void
init_inia100Adapter_table
(
void
);
/* ---- EXTERNAL FUNCTIONS ---- */
extern
void
inia100SCBPost
(
BYTE
*
pHcb
,
BYTE
*
pScb
);
extern
int
Addinia100_into_Adapter_table
(
WORD
,
WORD
,
struct
pci_dev
*
,
int
);
extern
int
init_inia100Adapter_table
(
int
);
extern
ORC_SCB
*
orc_alloc_scb
(
ORC_HCS
*
hcsp
);
extern
void
orc_exec_scb
(
ORC_HCS
*
hcsp
,
ORC_SCB
*
scbp
);
extern
void
orc_release_scb
(
ORC_HCS
*
hcsp
,
ORC_SCB
*
scbp
);
extern
void
orc_release_dma
(
ORC_HCS
*
hcsp
,
Scsi_Cmnd
*
cmnd
);
extern
void
orc_interrupt
(
ORC_HCS
*
hcsp
);
extern
int
orc_device_reset
(
ORC_HCS
*
pHCB
,
ULONG
SCpnt
,
unsigned
int
target
,
unsigned
int
ResetFlags
);
extern
int
orc_device_reset
(
ORC_HCS
*
pHCB
,
Scsi_Cmnd
*
SCpnt
,
unsigned
int
target
,
unsigned
int
ResetFlags
);
extern
int
orc_reset_scsi_bus
(
ORC_HCS
*
pHCB
);
extern
int
abort_SCB
(
ORC_HCS
*
hcsp
,
ORC_SCB
*
pScb
);
extern
int
orc_abort_srb
(
ORC_HCS
*
hcsp
,
ULONG
SCpnt
);
extern
int
orc_abort_srb
(
ORC_HCS
*
hcsp
,
Scsi_Cmnd
*
SCpnt
);
extern
void
get_orcPCIConfig
(
ORC_HCS
*
pCurHcb
,
int
ch_idx
);
extern
int
init_orchid
(
ORC_HCS
*
hcsp
);
extern
int
orc_num_scb
;
extern
ORC_HCS
orc_hcs
[];
extern
struct
inia100_Adpt_Struc
*
inia100_adpt
;
/*****************************************************************************
Function name : inia100AppendSRBToQueue
...
...
@@ -209,61 +202,62 @@ void inia100_setup(char *str, int *ints)
*****************************************************************************/
int
orc_ReturnNumberOfAdapters
(
void
)
{
unsigned
int
i
,
i
Adapters
;
unsigned
int
iAdapters
;
iAdapters
=
0
;
/*
* PCI-bus probe.
*/
if
(
pcibios_present
())
{
struct
{
unsigned
short
vendor_id
;
unsigned
short
device_id
;
}
const
inia100_pci_devices
[]
=
{
{
ORC_VENDOR_ID
,
I920_DEVICE_ID
},
{
ORC_VENDOR_ID
,
ORC_DEVICE_ID
}
};
/*
* Note: I removed the struct pci_device_list stuff since this
* driver only cares about one device ID. If that changes in
* the future it can be added in with only a very moderate
* amount of work. It made the double scan of the device list
* for getting a count and allocating the device list easier
* to not have the for(i ... ) loop in there....
*/
unsigned
int
dRegValue
;
WORD
wBIOS
,
wBASE
;
BYTE
bPCIBusNum
,
bInterrupt
,
bPCIDeviceNum
;
#ifdef MMAPIO
unsigned
long
page_offset
,
base
;
#endif
struct
pci_dev
*
pdev
=
NULL
;
bPCIBusNum
=
0
;
bPCIDeviceNum
=
0
;
init_inia100Adapter_table
();
for
(
i
=
0
;
i
<
NUMBER
(
inia100_pci_devices
);
i
++
)
{
/*
* Get a count of adapters that we expect to be able to use.
* Pass that count to init_inia100Adapter_table() for malloc
* reasons.
*/
pdev
=
NULL
;
while
((
pdev
=
pci_find_device
(
inia100_pci_devices
[
i
].
vendor_id
,
inia100_pci_devices
[
i
].
device_id
,
pdev
)))
while
((
pdev
=
pci_find_device
(
ORC_VENDOR_ID
,
ORC_DEVICE_ID
,
pdev
)))
{
if
(
pci_enable_device
(
pdev
))
continue
;
if
(
iAdapters
>=
MAX_SUPPORTED_ADAPTERS
)
break
;
/* Never greater than maximum */
if
(
i
==
0
)
{
if
(
pci_set_dma_mask
(
pdev
,
(
u64
)
0xffffffff
))
{
printk
(
KERN_WARNING
"Unable to set 32bit DMA "
"on inia100 adapter, ignoring.
\n
"
);
continue
;
}
iAdapters
++
;
}
if
(
init_inia100Adapter_table
(
iAdapters
))
return
0
;
/*
printk("inia100: The RAID controller is not supported by\n");
printk("inia100: this driver, we are ignoring it.\n");
* Now go through the adapters again actually setting them up
* and putting them in the table this time.
*/
}
else
{
pdev
=
NULL
;
while
((
pdev
=
pci_find_device
(
ORC_VENDOR_ID
,
ORC_DEVICE_ID
,
pdev
)))
{
/*
* Read sundry information from PCI BIOS.
*/
bPCIBusNum
=
pdev
->
bus
->
number
;
bPCIDeviceNum
=
pdev
->
devfn
;
dRegValue
=
pci_resource_start
(
pdev
,
0
);
if
(
dRegValue
==
-
1
)
{
/* Check return code */
printk
(
"
\n\r
inia100: orchid read configuration error.
\n
"
);
return
(
0
);
/* Read configuration space error */
iAdapters
--
;
continue
;
/* Read configuration space error */
}
/* <02> read from base address + 0x50 offset to get the wBIOS balue. */
...
...
@@ -271,7 +265,6 @@ int orc_ReturnNumberOfAdapters(void)
/* Now read the interrupt line value */
dRegValue
=
pdev
->
irq
;
bInterrupt
=
dRegValue
;
/* Assign interrupt line */
wBIOS
=
ORC_RDWORD
(
wBASE
,
0x50
);
...
...
@@ -291,12 +284,8 @@ int orc_ReturnNumberOfAdapters(void)
}
#endif
if
(
Addinia100_into_Adapter_table
(
wBIOS
,
wBASE
,
bInterrupt
,
bPCIBusNum
,
bPCIDeviceNum
)
==
SUCCESSFUL
)
iAdapters
++
;
}
Addinia100_into_Adapter_table
(
wBIOS
,
wBASE
,
pdev
,
iAdapters
);
}
/* while(pdev=....) */
}
/* for PCI_DEVICES */
}
/* PCI BIOS present */
return
(
iAdapters
);
}
...
...
@@ -317,8 +306,9 @@ int inia100_detect(Scsi_Host_Template * tpnt)
int
ok
=
0
,
iAdapters
;
ULONG
dBiosAdr
;
BYTE
*
pbBiosAdr
;
struct
pci_dev
*
pdev
;
tpnt
->
proc_name
=
"
INIA
100"
;
tpnt
->
proc_name
=
"
inia
100"
;
if
(
setup_called
)
{
/* Setup by inia100_setup */
printk
(
"inia100: processing commandline: "
);
...
...
@@ -330,44 +320,38 @@ int inia100_detect(Scsi_Host_Template * tpnt)
if
(
iAdapters
==
0
)
/* If no orc founded, return */
return
(
0
);
orc_num_ch
=
(
iAdapters
>
orc_num_ch
)
?
orc_num_ch
:
iAdapters
;
orc_num_scb
=
ORC_MAXQUEUE
;
/* clear the memory needed for HCS */
i
=
orc_num_ch
*
sizeof
(
ORC_HCS
);
memset
((
unsigned
char
*
)
&
orc_hcs
[
0
],
0
,
i
);
/* Initialize orc_hcs 0 */
#if 0
printk("orc_num_scb= %x orc_num_ch= %x hcsize= %x scbsize= %x escbsize= %x\n",
orc_num_scb, orc_num_ch, sizeof(ORC_HCS), sizeof(ORC_SCB), sizeof(ESCB));
#endif
for
(
i
=
0
,
pHCB
=
&
orc_hcs
[
0
];
/* Get pointer for control block */
i
<
orc_num_ch
;
i
++
,
pHCB
++
)
{
for
(
i
=
0
;
i
<
iAdapters
;
i
++
)
{
pdev
=
inia100_adpt
[
i
].
ADPT_pdev
;
hreg
=
scsi_register
(
tpnt
,
sizeof
(
ORC_HCS
));
if
(
hreg
==
NULL
)
{
goto
out_disable
;
}
pHCB
=
(
ORC_HCS
*
)
hreg
->
hostdata
;
pHCB
->
pdev
=
pdev
;
pHCB
->
pSRB_head
=
NULL
;
/* Initial SRB save queue */
pHCB
->
pSRB_tail
=
NULL
;
/* Initial SRB save queue */
pHCB
->
pSRB_lock
=
SPIN_LOCK_UNLOCKED
;
/* SRB save queue lock */
pHCB
->
BitAllocFlagLock
=
SPIN_LOCK_UNLOCKED
;
/* Get total memory needed for SCB */
sz
=
orc_num_scb
*
sizeof
(
ORC_SCB
);
if
((
pHCB
->
HCS_virScbArray
=
(
PVOID
)
kmalloc
(
sz
,
GFP_ATOMIC
|
GFP_DMA
))
==
NULL
)
{
sz
=
ORC_MAXQUEUE
*
sizeof
(
ORC_SCB
);
if
((
pHCB
->
HCS_virScbArray
=
(
PVOID
)
pci_alloc_consistent
(
pdev
,
sz
,
&
pHCB
->
HCS_physScbArray
))
==
NULL
)
{
printk
(
"inia100: SCB memory allocation error
\n
"
);
return
(
0
)
;
goto
out_unregister
;
}
memset
((
unsigned
char
*
)
pHCB
->
HCS_virScbArray
,
0
,
sz
);
pHCB
->
HCS_physScbArray
=
(
U32
)
VIRT_TO_BUS
(
pHCB
->
HCS_virScbArray
);
/* Get total memory needed for ESCB */
sz
=
orc_num_scb
*
sizeof
(
ESCB
);
if
((
pHCB
->
HCS_virEscbArray
=
(
PVOID
)
kmalloc
(
sz
,
GFP_ATOMIC
|
GFP_DMA
))
==
NULL
)
{
sz
=
ORC_MAXQUEUE
*
sizeof
(
ESCB
);
if
((
pHCB
->
HCS_virEscbArray
=
(
PVOID
)
pci_alloc_consistent
(
pdev
,
sz
,
&
pHCB
->
HCS_physEscbArray
))
==
NULL
)
{
printk
(
"inia100: ESCB memory allocation error
\n
"
);
/* ?? does pHCB->HCS_virtScbArray leak ??*/
return
(
0
);
goto
out_unalloc
;
}
memset
((
unsigned
char
*
)
pHCB
->
HCS_virEscbArray
,
0
,
sz
);
pHCB
->
HCS_physEscbArray
=
(
U32
)
VIRT_TO_BUS
(
pHCB
->
HCS_virEscbArray
);
get_orcPCIConfig
(
pHCB
,
i
);
...
...
@@ -378,30 +362,24 @@ int inia100_detect(Scsi_Host_Template * tpnt)
if
(
init_orchid
(
pHCB
))
{
/* Initial orchid chip */
printk
(
"inia100: initial orchid fail!!
\n
"
);
return
(
0
)
;
goto
out_unalloc
;
}
request_region
(
pHCB
->
HCS_Base
,
256
,
"inia100"
);
/* Register */
hreg
=
scsi_register
(
tpnt
,
sizeof
(
ORC_HCS
));
if
(
hreg
==
NULL
)
{
release_region
(
pHCB
->
HCS_Base
,
256
);
/* Register */
return
0
;
}
hreg
->
io_port
=
pHCB
->
HCS_Base
;
hreg
->
n_io_port
=
0xff
;
hreg
->
can_queue
=
orc_num_scb
;
/* 03/05/98 */
hreg
->
can_queue
=
ORC_MAXQUEUE
;
/* 03/05/98 */
hreg
->
unique_id
=
pHCB
->
HCS_Base
;
hreg
->
max_id
=
pHCB
->
HCS_MaxTar
;
hreg
->
max_lun
=
32
;
/* 10/21/97 */
hreg
->
max_lun
=
16
;
/* 10/21/97 */
/*
hreg->max_lun = 8;
hreg->max_channel = 1;
*/
hreg
->
irq
=
pHCB
->
HCS_Intr
;
hreg
->
this_id
=
pHCB
->
HCS_SCSI_ID
;
/* Assign HCS index */
hreg
->
base
=
(
unsigned
long
)
pHCB
;
#if 1
hreg
->
sg_tablesize
=
TOTAL_SG_ENTRY
;
/* Maximun support is 32 */
...
...
@@ -410,36 +388,7 @@ int inia100_detect(Scsi_Host_Template * tpnt)
#endif
/* Initial orc chip */
switch
(
i
)
{
case
0
:
ok
=
request_irq
(
pHCB
->
HCS_Intr
,
inia100_intr0
,
SA_INTERRUPT
|
SA_SHIRQ
,
"inia100"
,
hreg
);
break
;
case
1
:
ok
=
request_irq
(
pHCB
->
HCS_Intr
,
inia100_intr1
,
SA_INTERRUPT
|
SA_SHIRQ
,
"inia100"
,
hreg
);
break
;
case
2
:
ok
=
request_irq
(
pHCB
->
HCS_Intr
,
inia100_intr2
,
SA_INTERRUPT
|
SA_SHIRQ
,
"inia100"
,
hreg
);
break
;
case
3
:
ok
=
request_irq
(
pHCB
->
HCS_Intr
,
inia100_intr3
,
SA_INTERRUPT
|
SA_SHIRQ
,
"inia100"
,
hreg
);
break
;
case
4
:
ok
=
request_irq
(
pHCB
->
HCS_Intr
,
inia100_intr4
,
SA_INTERRUPT
|
SA_SHIRQ
,
"inia100"
,
hreg
);
break
;
case
5
:
ok
=
request_irq
(
pHCB
->
HCS_Intr
,
inia100_intr5
,
SA_INTERRUPT
|
SA_SHIRQ
,
"inia100"
,
hreg
);
break
;
case
6
:
ok
=
request_irq
(
pHCB
->
HCS_Intr
,
inia100_intr6
,
SA_INTERRUPT
|
SA_SHIRQ
,
"inia100"
,
hreg
);
break
;
case
7
:
ok
=
request_irq
(
pHCB
->
HCS_Intr
,
inia100_intr7
,
SA_INTERRUPT
|
SA_SHIRQ
,
"inia100"
,
hreg
);
break
;
default:
inia100_panic
(
"inia100: Too many host adapters
\n
"
);
break
;
}
ok
=
request_irq
(
pHCB
->
HCS_Intr
,
inia100_intr
,
SA_SHIRQ
,
"inia100"
,
hreg
);
if
(
ok
<
0
)
{
if
(
ok
==
-
EINVAL
)
{
printk
(
"inia100: bad IRQ %d.
\n
"
,
pHCB
->
HCS_Intr
);
...
...
@@ -453,13 +402,34 @@ int inia100_detect(Scsi_Host_Template * tpnt)
printk
(
" Contact author.
\n
"
);
}
}
inia100_panic
(
"inia100: driver needs an IRQ.
\n
"
)
;
goto
out_irq
;
}
}
tpnt
->
this_id
=
-
1
;
tpnt
->
can_queue
=
1
;
kfree
(
inia100_adpt
);
return
1
;
out_irq:
release_region
(
pHCB
->
HCS_Base
,
256
);
out_unalloc:
if
(
pHCB
->
HCS_virEscbArray
)
{
pci_free_consistent
(
pHCB
->
pdev
,
ORC_MAXQUEUE
*
sizeof
(
ESCB
),
pHCB
->
HCS_virEscbArray
,
pHCB
->
HCS_physEscbArray
);
pHCB
->
HCS_virEscbArray
=
NULL
;
}
if
(
pHCB
->
HCS_virScbArray
)
{
pci_free_consistent
(
pHCB
->
pdev
,
ORC_MAXQUEUE
*
sizeof
(
ORC_SCB
),
pHCB
->
HCS_virScbArray
,
pHCB
->
HCS_physScbArray
);
pHCB
->
HCS_virScbArray
=
NULL
;
}
out_unregister:
scsi_unregister
(
hreg
);
out_disable:
pci_disable_device
(
pdev
);
kfree
(
inia100_adpt
);
return
i
;
}
/*****************************************************************************
...
...
@@ -473,7 +443,7 @@ static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, Scsi_Cmnd * SCpnt)
{
/* Create corresponding SCB */
struct
scatterlist
*
pSrbSG
;
ORC_SG
*
pSG
;
/* Pointer to SG list */
int
i
;
int
i
,
count_sg
;
U32
TotalLen
;
ESCB
*
pEScb
;
...
...
@@ -493,17 +463,26 @@ static void inia100BuildSCB(ORC_HCS * pHCB, ORC_SCB * pSCB, Scsi_Cmnd * SCpnt)
pSG
=
(
ORC_SG
*
)
&
pEScb
->
ESCB_SGList
[
0
];
if
(
SCpnt
->
use_sg
)
{
TotalLen
=
0
;
pSCB
->
SCB_SGLen
=
(
U32
)
(
SCpnt
->
use_sg
*
8
);
pSrbSG
=
(
struct
scatterlist
*
)
SCpnt
->
request_buffer
;
for
(
i
=
0
;
i
<
SCpnt
->
use_sg
;
i
++
,
pSG
++
,
pSrbSG
++
)
{
pSG
->
SG_Ptr
=
(
U32
)
(
VIRT_TO_BUS
(
pSrbSG
->
address
));
pSG
->
SG_Len
=
(
U32
)
pSrbSG
->
length
;
TotalLen
+=
(
U32
)
pSrbSG
->
length
;
count_sg
=
pci_map_sg
(
pHCB
->
pdev
,
pSrbSG
,
SCpnt
->
use_sg
,
scsi_to_pci_dma_dir
(
SCpnt
->
sc_data_direction
));
pSCB
->
SCB_SGLen
=
(
U32
)
(
count_sg
*
8
);
for
(
i
=
0
;
i
<
count_sg
;
i
++
,
pSG
++
,
pSrbSG
++
)
{
pSG
->
SG_Ptr
=
(
U32
)
sg_dma_address
(
pSrbSG
);
pSG
->
SG_Len
=
(
U32
)
sg_dma_len
(
pSrbSG
);
TotalLen
+=
(
U32
)
sg_dma_len
(
pSrbSG
);
}
}
else
{
/* Non SG
*/
}
else
if
(
SCpnt
->
request_bufflen
!=
0
)
{
/* Non SG
*/
pSCB
->
SCB_SGLen
=
0x8
;
pSG
->
SG_Ptr
=
(
U32
)
(
VIRT_TO_BUS
(
SCpnt
->
request_buffer
));
pSG
->
SG_Ptr
=
(
U32
)
pci_map_single
(
pHCB
->
pdev
,
SCpnt
->
request_buffer
,
SCpnt
->
request_bufflen
,
scsi_to_pci_dma_dir
(
SCpnt
->
sc_data_direction
));
SCpnt
->
host_scribble
=
(
void
*
)
pSG
->
SG_Ptr
;
pSG
->
SG_Len
=
(
U32
)
SCpnt
->
request_bufflen
;
}
else
{
pSCB
->
SCB_SGLen
=
0
;
pSG
->
SG_Ptr
=
0
;
pSG
->
SG_Len
=
0
;
}
}
pSCB
->
SCB_SGPAddr
=
(
U32
)
pSCB
->
SCB_SensePAddr
;
...
...
@@ -538,12 +517,7 @@ int inia100_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
register
ORC_SCB
*
pSCB
;
ORC_HCS
*
pHCB
;
/* Point to Host adapter control block */
if
(
SCpnt
->
lun
>
16
)
{
SCpnt
->
result
=
(
DID_TIME_OUT
<<
16
);
done
(
SCpnt
);
/* Notify system DONE */
return
(
0
);
}
pHCB
=
(
ORC_HCS
*
)
SCpnt
->
host
->
base
;
pHCB
=
(
ORC_HCS
*
)
SCpnt
->
host
->
hostdata
;
SCpnt
->
scsi_done
=
done
;
/* Get free SCSI control block */
if
((
pSCB
=
orc_alloc_scb
(
pHCB
))
==
NULL
)
{
...
...
@@ -557,19 +531,6 @@ int inia100_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
return
(
0
);
}
/*****************************************************************************
Function name : inia100_command
Description : We only support command in interrupt-driven fashion
Input : pHCB - Pointer to host adapter structure
Output : None.
Return : pSRB - Pointer to SCSI request block.
*****************************************************************************/
int
inia100_command
(
Scsi_Cmnd
*
SCpnt
)
{
printk
(
"inia100: interrupt driven driver; use inia100_queue()
\n
"
);
return
-
1
;
}
/*****************************************************************************
Function name : inia100_abort
Description : Abort a queued command.
...
...
@@ -582,8 +543,8 @@ int inia100_abort(Scsi_Cmnd * SCpnt)
{
ORC_HCS
*
hcsp
;
hcsp
=
(
ORC_HCS
*
)
SCpnt
->
host
->
base
;
return
orc_abort_srb
(
hcsp
,
(
ULONG
)
SCpnt
);
hcsp
=
(
ORC_HCS
*
)
SCpnt
->
host
->
hostdata
;
return
orc_abort_srb
(
hcsp
,
SCpnt
);
}
/*****************************************************************************
...
...
@@ -597,12 +558,12 @@ int inia100_abort(Scsi_Cmnd * SCpnt)
int
inia100_reset
(
Scsi_Cmnd
*
SCpnt
,
unsigned
int
reset_flags
)
{
/* I need Host Control Block Information */
ORC_HCS
*
pHCB
;
pHCB
=
(
ORC_HCS
*
)
SCpnt
->
host
->
base
;
pHCB
=
(
ORC_HCS
*
)
SCpnt
->
host
->
hostdata
;
if
(
reset_flags
&
(
SCSI_RESET_SUGGEST_BUS_RESET
|
SCSI_RESET_SUGGEST_HOST_RESET
))
return
orc_reset_scsi_bus
(
pHCB
);
else
return
orc_device_reset
(
pHCB
,
(
ULONG
)
SCpnt
,
SCpnt
->
target
,
reset_flags
);
return
orc_device_reset
(
pHCB
,
SCpnt
,
SCpnt
->
target
,
reset_flags
);
}
...
...
@@ -672,14 +633,14 @@ void inia100SCBPost(BYTE * pHcb, BYTE * pScb)
(
unsigned
char
*
)
&
pEScb
->
ESCB_SGList
[
0
],
SENSE_SIZE
);
}
pSRB
->
result
=
pSCB
->
SCB_TaStat
|
(
pSCB
->
SCB_HaStat
<<
16
);
orc_release_dma
(
pHCB
,
pSRB
);
/* release DMA before we call scsi_done */
pSRB
->
scsi_done
(
pSRB
);
/* Notify system DONE */
/* Find the next pending SRB */
if
((
pSRB
=
inia100PopSRBFromQueue
(
pHCB
))
!=
NULL
)
{
/* Assume resend will success */
/* Reuse old SCB */
inia100BuildSCB
(
pHCB
,
pSCB
,
pSRB
);
/* Create corresponding SCB */
orc_exec_scb
(
pHCB
,
pSCB
);
/* Start execute SCB */
}
else
{
/* No Pending SRB */
}
else
{
orc_release_scb
(
pHCB
,
pSCB
);
/* Release SCB for current channel */
}
return
;
...
...
@@ -697,7 +658,7 @@ int inia100_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array)
ORC_HCS
*
pHcb
;
/* Point to Host adapter control block */
ORC_TCS
*
pTcb
;
pHcb
=
(
ORC_HCS
*
)
disk
->
device
->
host
->
base
;
pHcb
=
(
ORC_HCS
*
)
disk
->
device
->
host
->
hostdata
;
pTcb
=
&
pHcb
->
HCS_Tcs
[
disk
->
device
->
id
];
if
(
pTcb
->
TCS_DrvHead
)
{
...
...
@@ -719,62 +680,19 @@ int inia100_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array)
}
static
void
subIntr
(
ORC_HCS
*
pHCB
,
int
irqno
,
struct
Scsi_Host
*
dev
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
dev
->
host_lock
,
flags
);
if
(
pHCB
->
HCS_Intr
!=
irqno
)
{
spin_unlock_irqrestore
(
dev
->
host_lock
,
flags
);
return
;
}
orc_interrupt
(
pHCB
);
spin_unlock_irqrestore
(
dev
->
host_lock
,
flags
);
}
/*
* Interrupt
s
handler (main routine of the driver)
* Interrupt handler (main routine of the driver)
*/
static
void
inia100_intr
0
(
int
irqno
,
void
*
dev_
id
,
struct
pt_regs
*
regs
)
static
void
inia100_intr
(
int
irqno
,
void
*
dev
id
,
struct
pt_regs
*
regs
)
{
subIntr
(
&
orc_hcs
[
0
],
irqno
,
dev_id
);
}
static
void
inia100_intr1
(
int
irqno
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
subIntr
(
&
orc_hcs
[
1
],
irqno
,
dev_id
);
}
static
void
inia100_intr2
(
int
irqno
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
subIntr
(
&
orc_hcs
[
2
],
irqno
,
dev_id
);
}
static
void
inia100_intr3
(
int
irqno
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
subIntr
(
&
orc_hcs
[
3
],
irqno
,
dev_id
);
}
static
void
inia100_intr4
(
int
irqno
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
subIntr
(
&
orc_hcs
[
4
],
irqno
,
dev_id
);
}
static
void
inia100_intr5
(
int
irqno
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
subIntr
(
&
orc_hcs
[
5
],
irqno
,
dev_id
);
}
static
void
inia100_intr6
(
int
irqno
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
subIntr
(
&
orc_hcs
[
6
],
irqno
,
dev_id
);
}
struct
Scsi_Host
*
host
=
(
struct
Scsi_Host
*
)
devid
;
ORC_HCS
*
pHcb
;
unsigned
long
flags
;
static
void
inia100_intr7
(
int
irqno
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
subIntr
(
&
orc_hcs
[
7
],
irqno
,
dev_id
);
pHcb
=
(
ORC_HCS
*
)
host
->
hostdata
;
/* Host adapter control block */
spin_lock_irqsave
(
host
->
host_lock
,
flags
);
orc_interrupt
(
pHcb
);
spin_unlock_irqrestore
(
host
->
host_lock
,
flags
);
}
/*
...
...
@@ -791,8 +709,21 @@ static void inia100_panic(char *msg)
*/
int
inia100_release
(
struct
Scsi_Host
*
hreg
)
{
ORC_HCS
*
pHCB
=
(
ORC_HCS
*
)
hreg
->
hostdata
;
free_irq
(
hreg
->
irq
,
hreg
);
release_region
(
hreg
->
io_port
,
256
);
if
(
pHCB
->
HCS_virEscbArray
)
{
pci_free_consistent
(
pHCB
->
pdev
,
ORC_MAXQUEUE
*
sizeof
(
ESCB
),
pHCB
->
HCS_virEscbArray
,
pHCB
->
HCS_physEscbArray
);
pHCB
->
HCS_virEscbArray
=
NULL
;
}
if
(
pHCB
->
HCS_virScbArray
)
{
pci_free_consistent
(
pHCB
->
pdev
,
ORC_MAXQUEUE
*
sizeof
(
ORC_SCB
),
pHCB
->
HCS_virScbArray
,
pHCB
->
HCS_physScbArray
);
pHCB
->
HCS_virScbArray
=
NULL
;
}
pci_disable_device
(
pHCB
->
pdev
);
return
0
;
}
...
...
drivers/scsi/inia100.h
View file @
7403ed3e
...
...
@@ -58,6 +58,9 @@
* Revision History:
* 06/18/98 HL, Initial production Version 1.02
* 12/19/98 bv, Use spinlocks for 2.1.95 and up
* 06/25/02 Doug Ledford <dledford@redhat.com>
* - This and the i60uscsi.h file are almost identical,
* merged them into a single header used by both .c files.
****************************************************************************/
#ifndef CVT_LINUX_VERSION
...
...
@@ -68,13 +71,14 @@
#include <linux/version.h>
#endif
#include <linux/config.h>
#include <linux/types.h>
#include <linux/pci.h>
#include "sd.h"
extern
int
inia100_detect
(
Scsi_Host_Template
*
);
extern
int
inia100_release
(
struct
Scsi_Host
*
);
extern
int
inia100_command
(
Scsi_Cmnd
*
);
extern
int
inia100_queue
(
Scsi_Cmnd
*
,
void
(
*
done
)
(
Scsi_Cmnd
*
));
extern
int
inia100_abort
(
Scsi_Cmnd
*
);
extern
int
inia100_reset
(
Scsi_Cmnd
*
,
unsigned
int
);
...
...
@@ -86,13 +90,13 @@ extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */
#define INIA100 { \
next: NULL, \
module: NULL, \
proc_name: "
INIA
100", \
proc_name: "
inia
100", \
proc_info: NULL, \
name: inia100_REVID, \
detect: inia100_detect, \
release: inia100_release, \
info: NULL, \
command:
inia100_command
, \
command:
NULL
, \
queuecommand: inia100_queue, \
eh_strategy_handler: NULL, \
eh_abort_handler: NULL, \
...
...
@@ -112,7 +116,6 @@ extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */
use_clustering: ENABLE_CLUSTERING, \
}
#define VIRT_TO_BUS(i) (unsigned int) virt_to_bus((void *)(i))
#define ULONG unsigned long
#define PVOID void *
#define USHORT unsigned short
...
...
@@ -139,15 +142,16 @@ extern int inia100_biosparam(Scsi_Disk *, kdev_t, int *); /*for linux v2.0 */
#endif
#if 1
#define ORC_MAXQUEUE 245
#define ORC_MAXTAGS 64
#else
#define ORC_MAXQUEUE 25
#define ORC_MAXTAGS 8
#endif
#define TOTAL_SG_ENTRY 32
#define MAX_TARGETS 16
#define IMAX_CDB 15
#define SENSE_SIZE 14
#define MAX_SUPPORTED_ADAPTERS 4
#define SUCCESSFUL 0x00
#define I920_DEVICE_ID 0x0002
/* Initio's inic-950 product ID */
...
...
@@ -160,6 +164,12 @@ typedef struct ORC_SG_Struc {
U32
SG_Len
;
/* Data Length */
}
ORC_SG
;
typedef
struct
inia100_Adpt_Struc
{
UWORD
ADPT_BIOS
;
/* 0 */
UWORD
ADPT_BASE
;
/* 1 */
struct
pci_dev
*
ADPT_pdev
;
/* 2 */
}
INIA100_ADPT_STRUCT
;
/* SCSI related definition */
#define DISC_NOT_ALLOW 0x80
/* Disconnect is not allowed */
...
...
@@ -374,9 +384,9 @@ typedef struct ORC_Ha_Ctrl_Struc {
USHORT
HCS_AFlags
;
/* Adapter info. defined flags */
ULONG
HCS_Timeout
;
/* Adapter timeout value */
PVOID
HCS_virScbArray
;
/* 28 Virtual Pointer to SCB array */
U32
HCS_physScbArray
;
/* Scb Physical address */
dma_addr_t
HCS_physScbArray
;
/* Scb Physical address */
PVOID
HCS_virEscbArray
;
/* Virtual pointer to ESCB Scatter list */
U32
HCS_physEscbArray
;
/* scatter list Physical address */
dma_addr_t
HCS_physEscbArray
;
/* scatter list Physical address */
UBYTE
TargetFlag
[
16
];
/* 30 target configuration, TCF_EN_TAG */
UBYTE
MaximumTags
[
16
];
/* 40 ORC_MAX_SCBS */
UBYTE
ActiveTags
[
16
][
16
];
/* 50 */
...
...
@@ -386,6 +396,7 @@ typedef struct ORC_Ha_Ctrl_Struc {
Scsi_Cmnd
*
pSRB_head
;
Scsi_Cmnd
*
pSRB_tail
;
spinlock_t
pSRB_lock
;
struct
pci_dev
*
pdev
;
}
ORC_HCS
;
/* Bit Definition for HCS_Flags */
...
...
@@ -438,3 +449,148 @@ typedef struct ORC_Ha_Ctrl_Struc {
/*----------------------------------------------*/
#define MAX_PCI_DEVICES 21
#define MAX_PCI_BUSES 8
typedef
struct
Adpt_Struc
{
USHORT
ADPT_BIOS
;
/* 0 */
UBYTE
ADPT_BASE
;
/* 1 */
UBYTE
ADPT_Bus
;
/* 2 */
UBYTE
ADPT_Device
;
/* 3 */
UBYTE
ADPT_Reserved
[
3
];
}
JACS
,
*
PJACS
;
typedef
struct
_NVRAM
{
/*----------header ---------------*/
UCHAR
SubVendorID0
;
/* 00 - Sub Vendor ID */
UCHAR
SubVendorID1
;
/* 00 - Sub Vendor ID */
UCHAR
SubSysID0
;
/* 02 - Sub System ID */
UCHAR
SubSysID1
;
/* 02 - Sub System ID */
UCHAR
SubClass
;
/* 04 - Sub Class */
UCHAR
VendorID0
;
/* 05 - Vendor ID */
UCHAR
VendorID1
;
/* 05 - Vendor ID */
UCHAR
DeviceID0
;
/* 07 - Device ID */
UCHAR
DeviceID1
;
/* 07 - Device ID */
UCHAR
Reserved0
[
2
];
/* 09 - Reserved */
UCHAR
Revision
;
/* 0B - Revision of data structure */
/* ----Host Adapter Structure ---- */
UCHAR
NumOfCh
;
/* 0C - Number of SCSI channel */
UCHAR
BIOSConfig1
;
/* 0D - BIOS configuration 1 */
UCHAR
BIOSConfig2
;
/* 0E - BIOS boot channel&target ID */
UCHAR
BIOSConfig3
;
/* 0F - BIOS configuration 3 */
/* ----SCSI channel Structure ---- */
/* from "CTRL-I SCSI Host Adapter SetUp menu " */
UCHAR
SCSI0Id
;
/* 10 - Channel 0 SCSI ID */
UCHAR
SCSI0Config
;
/* 11 - Channel 0 SCSI configuration */
UCHAR
SCSI0MaxTags
;
/* 12 - Channel 0 Maximum tags */
UCHAR
SCSI0ResetTime
;
/* 13 - Channel 0 Reset recovering time */
UCHAR
ReservedforChannel0
[
2
];
/* 14 - Reserved */
/* ----SCSI target Structure ---- */
/* from "CTRL-I SCSI device SetUp menu " */
UCHAR
Target00Config
;
/* 16 - Channel 0 Target 0 config */
UCHAR
Target01Config
;
/* 17 - Channel 0 Target 1 config */
UCHAR
Target02Config
;
/* 18 - Channel 0 Target 2 config */
UCHAR
Target03Config
;
/* 19 - Channel 0 Target 3 config */
UCHAR
Target04Config
;
/* 1A - Channel 0 Target 4 config */
UCHAR
Target05Config
;
/* 1B - Channel 0 Target 5 config */
UCHAR
Target06Config
;
/* 1C - Channel 0 Target 6 config */
UCHAR
Target07Config
;
/* 1D - Channel 0 Target 7 config */
UCHAR
Target08Config
;
/* 1E - Channel 0 Target 8 config */
UCHAR
Target09Config
;
/* 1F - Channel 0 Target 9 config */
UCHAR
Target0AConfig
;
/* 20 - Channel 0 Target A config */
UCHAR
Target0BConfig
;
/* 21 - Channel 0 Target B config */
UCHAR
Target0CConfig
;
/* 22 - Channel 0 Target C config */
UCHAR
Target0DConfig
;
/* 23 - Channel 0 Target D config */
UCHAR
Target0EConfig
;
/* 24 - Channel 0 Target E config */
UCHAR
Target0FConfig
;
/* 25 - Channel 0 Target F config */
UCHAR
SCSI1Id
;
/* 26 - Channel 1 SCSI ID */
UCHAR
SCSI1Config
;
/* 27 - Channel 1 SCSI configuration */
UCHAR
SCSI1MaxTags
;
/* 28 - Channel 1 Maximum tags */
UCHAR
SCSI1ResetTime
;
/* 29 - Channel 1 Reset recovering time */
UCHAR
ReservedforChannel1
[
2
];
/* 2A - Reserved */
/* ----SCSI target Structure ---- */
/* from "CTRL-I SCSI device SetUp menu " */
UCHAR
Target10Config
;
/* 2C - Channel 1 Target 0 config */
UCHAR
Target11Config
;
/* 2D - Channel 1 Target 1 config */
UCHAR
Target12Config
;
/* 2E - Channel 1 Target 2 config */
UCHAR
Target13Config
;
/* 2F - Channel 1 Target 3 config */
UCHAR
Target14Config
;
/* 30 - Channel 1 Target 4 config */
UCHAR
Target15Config
;
/* 31 - Channel 1 Target 5 config */
UCHAR
Target16Config
;
/* 32 - Channel 1 Target 6 config */
UCHAR
Target17Config
;
/* 33 - Channel 1 Target 7 config */
UCHAR
Target18Config
;
/* 34 - Channel 1 Target 8 config */
UCHAR
Target19Config
;
/* 35 - Channel 1 Target 9 config */
UCHAR
Target1AConfig
;
/* 36 - Channel 1 Target A config */
UCHAR
Target1BConfig
;
/* 37 - Channel 1 Target B config */
UCHAR
Target1CConfig
;
/* 38 - Channel 1 Target C config */
UCHAR
Target1DConfig
;
/* 39 - Channel 1 Target D config */
UCHAR
Target1EConfig
;
/* 3A - Channel 1 Target E config */
UCHAR
Target1FConfig
;
/* 3B - Channel 1 Target F config */
UCHAR
reserved
[
3
];
/* 3C - Reserved */
/* ---------- CheckSum ---------- */
UCHAR
CheckSum
;
/* 3F - Checksum of NVRam */
}
NVRAM
,
*
PNVRAM
;
/* Bios Configuration for nvram->BIOSConfig1 */
#define NBC_BIOSENABLE 0x01
/* BIOS enable */
#define NBC_CDROM 0x02
/* Support bootable CDROM */
#define NBC_REMOVABLE 0x04
/* Support removable drive */
/* Bios Configuration for nvram->BIOSConfig2 */
#define NBB_TARGET_MASK 0x0F
/* Boot SCSI target ID number */
#define NBB_CHANL_MASK 0xF0
/* Boot SCSI channel number */
/* Bit definition for nvram->SCSIConfig */
#define NCC_BUSRESET 0x01
/* Reset SCSI bus at power up */
#define NCC_PARITYCHK 0x02
/* SCSI parity enable */
#define NCC_LVDS 0x10
/* Enable LVDS */
#define NCC_ACTTERM1 0x20
/* Enable active terminator 1 */
#define NCC_ACTTERM2 0x40
/* Enable active terminator 2 */
#define NCC_AUTOTERM 0x80
/* Enable auto termination */
/* Bit definition for nvram->TargetxConfig */
#define NTC_PERIOD 0x07
/* Maximum Sync. Speed */
#define NTC_1GIGA 0x08
/* 255 head / 63 sectors (64/32) */
#define NTC_NO_SYNC 0x10
/* NO SYNC. NEGO */
#define NTC_NO_WIDESYNC 0x20
/* NO WIDE SYNC. NEGO */
#define NTC_DISC_ENABLE 0x40
/* Enable SCSI disconnect */
#define NTC_SPINUP 0x80
/* Start disk drive */
/* Default NVRam values */
#define NBC_DEFAULT (NBC_ENABLE)
#define NCC_DEFAULT (NCC_BUSRESET | NCC_AUTOTERM | NCC_PARITYCHK)
#define NCC_MAX_TAGS 0x20
/* Maximum tags per target */
#define NCC_RESET_TIME 0x0A
/* SCSI RESET recovering time */
#define NTC_DEFAULT (NTC_1GIGA | NTC_NO_WIDESYNC | NTC_DISC_ENABLE)
typedef
union
{
/* Union define for mechanism 1 */
struct
{
unsigned
char
RegNum
;
unsigned
char
FcnNum
:
3
;
unsigned
char
DeviceNum
:
5
;
unsigned
char
BusNum
;
unsigned
char
Reserved
:
7
;
unsigned
char
Enable
:
1
;
}
sConfigAdr
;
unsigned
long
lConfigAdr
;
}
CONFIG_ADR
;
typedef
union
{
/* Union define for mechanism 2 */
struct
{
unsigned
char
RegNum
;
unsigned
char
DeviceNum
;
unsigned
short
Reserved
;
}
sHostAdr
;
unsigned
long
lHostAdr
;
}
HOST_ADR
;
#define ORC_RD(x,y) (UCHAR)(inb( (int)((ULONG)((ULONG)x+(UCHAR)y)) ))
#define ORC_RDLONG(x,y) (long)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
#define ORC_WR( adr,data) outb( (UCHAR)(data), (int)(adr))
#define ORC_WRSHORT(adr,data) outw( (UWORD)(data), (int)(adr))
#define ORC_WRLONG( adr,data) outl( (ULONG)(data), (int)(adr))
drivers/video/matrox/matroxfb_base.c
View file @
7403ed3e
...
...
@@ -141,6 +141,19 @@ static struct fb_var_screeninfo vesafb_defined = {
/* --------------------------------------------------------------------- */
static
inline
void
my_install_cmap
(
WPMINFO2
)
{
/* Do not touch this code if you do not understand what it does! */
/* Never try to use do_install_cmap() instead. It is crap. */
struct
fb_cmap
*
cmap
=
&
ACCESS_FBINFO
(
currcon_display
)
->
cmap
;
if
(
cmap
->
len
)
fb_set_cmap
(
cmap
,
1
,
&
ACCESS_FBINFO
(
fbcon
));
else
fb_set_cmap
(
fb_default_cmap
(
ACCESS_FBINFO
(
curr
.
cmap_len
)),
1
,
&
ACCESS_FBINFO
(
fbcon
));
}
static
void
matrox_pan_var
(
WPMINFO
struct
fb_var_screeninfo
*
var
)
{
unsigned
int
pos
;
...
...
@@ -869,7 +882,7 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
up_read
(
&
ACCESS_FBINFO
(
altout
.
lock
));
}
matrox_cfbX_init
(
PMINFO
display
);
do_install_cmap
(
ACCESS_FBINFO
(
fbcon
.
currcon
),
&
ACCESS_FBINFO
(
fbcon
)
);
my_install_cmap
(
PMINFO2
);
#if defined(CONFIG_FB_COMPAT_XPMAC)
if
(
console_fb_info
==
&
ACCESS_FBINFO
(
fbcon
))
{
int
vmode
,
cmode
;
...
...
drivers/video/matrox/matroxfb_crtc2.c
View file @
7403ed3e
...
...
@@ -29,7 +29,7 @@ MODULE_PARM_DESC(mem, "Memory size reserved for dualhead (default=8MB)");
static
int
matroxfb_dh_getcolreg
(
unsigned
regno
,
unsigned
*
red
,
unsigned
*
green
,
unsigned
*
blue
,
unsigned
*
transp
,
struct
fb_info
*
info
)
{
#define m2info ((struct matroxfb_dh_fb_info*)info)
if
(
regno
>
16
)
if
(
regno
>
=
16
)
return
1
;
*
red
=
m2info
->
palette
[
regno
].
red
;
*
blue
=
m2info
->
palette
[
regno
].
blue
;
...
...
@@ -44,7 +44,7 @@ static int matroxfb_dh_setcolreg(unsigned regno, unsigned red, unsigned green,
#define m2info ((struct matroxfb_dh_fb_info*)info)
struct
display
*
p
;
if
(
regno
>
16
)
if
(
regno
>
=
16
)
return
1
;
m2info
->
palette
[
regno
].
red
=
red
;
m2info
->
palette
[
regno
].
blue
=
blue
;
...
...
@@ -84,6 +84,19 @@ static int matroxfb_dh_setcolreg(unsigned regno, unsigned red, unsigned green,
#undef m2info
}
static
inline
void
my_install_cmap
(
struct
matroxfb_dh_fb_info
*
m2info
)
{
/* Do not touch this code if you do not understand what it does! */
/* Never try to use do_install_cmap() instead. It is crap. */
struct
fb_cmap
*
cmap
=
&
m2info
->
currcon_display
->
cmap
;
if
(
cmap
->
len
)
fb_set_cmap
(
cmap
,
1
,
&
m2info
->
fbcon
);
else
fb_set_cmap
(
fb_default_cmap
(
16
),
1
,
&
m2info
->
fbcon
);
}
static
void
matroxfb_dh_restore
(
struct
matroxfb_dh_fb_info
*
m2info
,
struct
my_timming
*
mt
,
struct
display
*
p
,
...
...
@@ -439,7 +452,7 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con,
up_read
(
&
ACCESS_FBINFO
(
altout
.
lock
));
}
matroxfb_dh_cfbX_init
(
m2info
,
p
);
do_install_cmap
(
ACCESS_FBINFO
(
fbcon
.
currcon
),
&
ACCESS_FBINFO
(
fbcon
)
);
my_install_cmap
(
m2info
);
}
return
0
;
#undef m2info
...
...
fs/binfmt_elf.c
View file @
7403ed3e
...
...
@@ -1124,14 +1124,10 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
psinfo
.
pr_ppid
=
prstatus
.
pr_ppid
=
current
->
parent
->
pid
;
psinfo
.
pr_pgrp
=
prstatus
.
pr_pgrp
=
current
->
pgrp
;
psinfo
.
pr_sid
=
prstatus
.
pr_sid
=
current
->
session
;
prstatus
.
pr_utime
.
tv_sec
=
CT_TO_SECS
(
current
->
times
.
tms_utime
);
prstatus
.
pr_utime
.
tv_usec
=
CT_TO_USECS
(
current
->
times
.
tms_utime
);
prstatus
.
pr_stime
.
tv_sec
=
CT_TO_SECS
(
current
->
times
.
tms_stime
);
prstatus
.
pr_stime
.
tv_usec
=
CT_TO_USECS
(
current
->
times
.
tms_stime
);
prstatus
.
pr_cutime
.
tv_sec
=
CT_TO_SECS
(
current
->
times
.
tms_cutime
);
prstatus
.
pr_cutime
.
tv_usec
=
CT_TO_USECS
(
current
->
times
.
tms_cutime
);
prstatus
.
pr_cstime
.
tv_sec
=
CT_TO_SECS
(
current
->
times
.
tms_cstime
);
prstatus
.
pr_cstime
.
tv_usec
=
CT_TO_USECS
(
current
->
times
.
tms_cstime
);
jiffies_to_timeval
(
current
->
utime
,
&
prstatus
.
pr_utime
);
jiffies_to_timeval
(
current
->
stime
,
&
prstatus
.
pr_stime
);
jiffies_to_timeval
(
current
->
cutime
,
&
prstatus
.
pr_cutime
);
jiffies_to_timeval
(
current
->
cstime
,
&
prstatus
.
pr_cstime
);
#ifdef DEBUG
dump_regs
(
"Passed in regs"
,
(
elf_greg_t
*
)
regs
);
...
...
fs/ntfs/ChangeLog
View file @
7403ed3e
...
...
@@ -6,7 +6,7 @@ ToDo:
user open()s a file with i_size > s_maxbytes? Should read_inode()
truncate the visible i_size? Will the user just get -E2BIG (or
whatever) on open()? Or will (s)he be able to open() but lseek() and
read() will fail when s_maxbytes is reached? -> Investigate this
!
read() will fail when s_maxbytes is reached? -> Investigate this
.
- Implement/allow non-resident index bitmaps in dir.c::ntfs_readdir()
and then also consider initialized_size w.r.t. the bitmaps, etc.
- vcn_to_lcn() should somehow return the correct pointer within the
...
...
@@ -17,11 +17,67 @@ ToDo:
- Consider if ntfs_file_read_compressed_block() shouldn't be coping
with initialized_size < data_size. I don't think it can happen but
it requires more careful consideration.
- CLEANUP: Modularise and reuse code in aops.c. At the moment we have
several copies of almost identicall functions and the functions are
quite big. Modularising them a bit, e.g. a-la get_block(), will make
them cleaner and make code reuse easier.
- Want to use dummy inodes for address space i/o.
- CLEANUP: At the moment we have two copies of almost identical
functions in aops.c, can merge them once fake inode address space
based attribute i/o is further developed.
- CLEANUP: Modularising code in aops.c a bit, e.g. a-la get_block(),
will be cleaner and make code reuse easier.
- Modify ntfs_read_locked_inode() to return an error code and update
callers, i.e. ntfs_iget(), to pass that error code up instead of just
using -EIO.
- Enable NFS exporting of NTFS.
- Use fake inodes for address space i/o.
2.0.13 - Use iget5_locked() in preparation for fake inodes and small cleanups.
- Remove nr_mft_bits and the now superfluous union with nr_mft_records
from ntfs_volume structure.
- Remove nr_lcn_bits and the now superfluous union with nr_clusters
from ntfs_volume structure.
- Use iget5_locked() and friends instead of conventional iget(). Wrap
the call in fs/ntfs/inode.c::ntfs_iget() and update callers of iget()
to use ntfs_iget(). Leave only one iget() call at mount time so we
don't need an ntfs_iget_mount().
- Change fs/ntfs/inode.c::ntfs_new_extent_inode() to take mft_no as an
additional argument.
2.0.12 - Initial cleanup of address space operations following 2.0.11 changes.
- Merge fs/ntfs/aops.c::end_buffer_read_mst_async() and
fs/ntfs/aops.c::end_buffer_read_file_async() into one function
fs/ntfs/aops.c::end_buffer_read_attr_async() using NInoMstProtected()
to determine whether to apply mst fixups or not.
- Above change allows merging fs/ntfs/aops.c::ntfs_file_read_block()
and fs/ntfs/aops.c::ntfs_mst_readpage() into one function
fs/ntfs/aops.c::ntfs_attr_read_block(). Also, create a tiny wrapper
fs/ntfs/aops.c::ntfs_mst_readpage() to transform the parameters from
the VFS readpage function prototype to the ntfs_attr_read_block()
function prototype.
2.0.11 - Initial preparations for fake inode based attribute i/o.
- Move definition of ntfs_inode_state_bits to fs/ntfs/inode.h and
do some macro magic (adapted from include/linux/buffer_head.h) to
expand all the helper functions NInoFoo(), NInoSetFoo(), and
NInoClearFoo().
- Add new flag to ntfs_inode_state_bits: NI_Sparse.
- Add new fields to ntfs_inode structure to allow use of fake inodes
for attribute i/o: type, name, name_len. Also add new state bits:
NI_Attr, which, if set, indicates the inode is a fake inode, and
NI_MstProtected, which, if set, indicates the attribute uses multi
sector transfer protection, i.e. fixups need to be applied after
reads and before/after writes.
- Rename fs/ntfs/inode.c::ntfs_{new,clear,destroy}_inode() to
ntfs_{new,clear,destroy}_extent_inode() and update callers.
- Use ntfs_clear_extent_inode() in fs/ntfs/inode.c::__ntfs_clear_inode()
instead of ntfs_destroy_extent_inode().
- Cleanup memory deallocations in {__,}ntfs_clear_{,big_}inode().
- Make all operations on ntfs inode state bits use the NIno* functions.
- Set up the new ntfs inode fields and state bits in
fs/ntfs/inode.c::ntfs_read_inode() and add appropriate cleanup of
allocated memory to __ntfs_clear_inode().
- Cleanup ntfs_inode structure a bit for better ordering of elements
w.r.t. their size to allow better packing of the structure in memory.
2.0.10 - There can only be 2^32 - 1 inodes on an NTFS volume.
...
...
@@ -38,7 +94,10 @@ ToDo:
- Change decompression engine to use a single buffer protected by a
spin lock instead of per-CPU buffers. (Rusty Russell)
- Switch to using the new KM_BIO_SRC_IRQ for atomic kmaps. (Andrew
- Do not update cb_pos when handling a partial final page during
decompression of a sparse compression block, as the value is later
reset without being read/used. (Rusty Russell)
- Switch to using the new KM_BIO_SRC_IRQ for atomic kmap()s. (Andrew
Morton)
- Change buffer size in ntfs_readdir()/ntfs_filldir() to use
NLS_MAX_CHARSET_SIZE which makes the buffers almost 1kiB each but
...
...
fs/ntfs/Makefile
View file @
7403ed3e
...
...
@@ -5,7 +5,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs.o
ntfs-objs
:=
aops.o attrib.o compress.o debug.o dir.o file.o inode.o mft.o
\
mst.o namei.o super.o sysctl.o time.o unistr.o upcase.o
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.0.1
0
\"
EXTRA_CFLAGS
=
-DNTFS_VERSION
=
\"
2.0.1
3
\"
ifeq
($(CONFIG_NTFS_DEBUG),y)
EXTRA_CFLAGS
+=
-DDEBUG
...
...
fs/ntfs/aops.c
View file @
7403ed3e
...
...
@@ -3,7 +3,7 @@
* Part of the Linux-NTFS project.
*
* Copyright (c) 2001,2002 Anton Altaparmakov.
* Copyright (
C
) 2002 Richard Russon.
* Copyright (
c
) 2002 Richard Russon.
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
...
...
@@ -30,31 +30,43 @@
#include "ntfs.h"
/**
* end_buffer_read_file_async -
* end_buffer_read_attr_async - async io completion for reading attributes
* @bh: buffer head on which io is completed
* @uptodate: whether @bh is now uptodate or not
*
* Async io completion handler for accessing files. Adapted from
* end_buffer_read_mst_async().
* Asynchronous I/O completion handler for reading pages belonging to the
* attribute address space of an inode. The inodes can either be files or
* directories or they can be fake inodes describing some attribute.
*
* If NInoMstProtected(), perform the post read mst fixups when all IO on the
* page has been completed and mark the page uptodate or set the error bit on
* the page. To determine the size of the records that need fixing up, we cheat
* a little bit by setting the index_block_size in ntfs_inode to the ntfs
* record size, and index_block_size_bits, to the log(base 2) of the ntfs
* record size.
*/
static
void
end_buffer_read_
file
_async
(
struct
buffer_head
*
bh
,
int
uptodate
)
static
void
end_buffer_read_
attr
_async
(
struct
buffer_head
*
bh
,
int
uptodate
)
{
static
spinlock_t
page_uptodate_lock
=
SPIN_LOCK_UNLOCKED
;
unsigned
long
flags
;
struct
buffer_head
*
tmp
;
struct
page
*
page
;
ntfs_inode
*
ni
;
if
(
uptodate
)
if
(
likely
(
uptodate
)
)
set_buffer_uptodate
(
bh
);
else
clear_buffer_uptodate
(
bh
);
page
=
bh
->
b_page
;
ni
=
NTFS_I
(
page
->
mapping
->
host
);
if
(
likely
(
uptodate
))
{
s64
file_ofs
;
ntfs_inode
*
ni
=
NTFS_I
(
page
->
mapping
->
host
);
file_ofs
=
(
page
->
index
<<
PAGE_CACHE_SHIFT
)
+
bh_offset
(
bh
);
/* Check for the current buffer head overflowing. */
if
(
file_ofs
+
bh
->
b_size
>
ni
->
initialized_size
)
{
char
*
addr
;
int
ofs
=
0
;
...
...
@@ -82,10 +94,47 @@ static void end_buffer_read_file_async(struct buffer_head *bh, int uptodate)
SetPageError
(
page
);
tmp
=
tmp
->
b_this_page
;
}
spin_unlock_irqrestore
(
&
page_uptodate_lock
,
flags
);
if
(
!
PageError
(
page
))
/*
* If none of the buffers had errors then we can set the page uptodate,
* but we first have to perform the post read mst fixups, if the
* attribute is mst protected, i.e. if NInoMstProteced(ni) is true.
*/
if
(
!
NInoMstProtected
(
ni
))
{
if
(
likely
(
!
PageError
(
page
)))
SetPageUptodate
(
page
);
unlock_page
(
page
);
return
;
}
else
{
char
*
addr
;
unsigned
int
i
,
recs
,
nr_err
;
u32
rec_size
;
rec_size
=
ni
->
_IDM
(
index_block_size
);
recs
=
PAGE_CACHE_SIZE
/
rec_size
;
addr
=
kmap_atomic
(
page
,
KM_BIO_SRC_IRQ
);
for
(
i
=
nr_err
=
0
;
i
<
recs
;
i
++
)
{
if
(
likely
(
!
post_read_mst_fixup
((
NTFS_RECORD
*
)(
addr
+
i
*
rec_size
),
rec_size
)))
continue
;
nr_err
++
;
ntfs_error
(
ni
->
vol
->
sb
,
"post_read_mst_fixup() failed, "
"corrupt %s record 0x%Lx. Run chkdsk."
,
ni
->
mft_no
?
"index"
:
"mft"
,
(
long
long
)(((
s64
)
page
->
index
<<
PAGE_CACHE_SHIFT
>>
ni
->
_IDM
(
index_block_size_bits
))
+
i
));
}
flush_dcache_page
(
page
);
kunmap_atomic
(
addr
,
KM_BIO_SRC_IRQ
);
if
(
likely
(
!
nr_err
&&
recs
))
SetPageUptodate
(
page
);
else
{
ntfs_error
(
ni
->
vol
->
sb
,
"Setting page error, index "
"0x%lx."
,
page
->
index
);
SetPageError
(
page
);
}
}
unlock_page
(
page
);
return
;
still_busy:
...
...
@@ -94,11 +143,20 @@ static void end_buffer_read_file_async(struct buffer_head *bh, int uptodate)
}
/**
* ntfs_file_read_block -
* ntfs_attr_read_block - fill a @page of an address space with data
* @page: page cache page to fill with data
*
* NTFS version of block_read_full_page(). Adapted from ntfs_mst_readpage().
* Fill the page @page of the address space belonging to the @page->host inode.
* We read each buffer asynchronously and when all buffers are read in, our io
* completion handler end_buffer_read_attr_async(), if required, automatically
* applies the mst fixups to the page before finally marking it uptodate and
* unlocking it.
*
* Return 0 on success and -errno on error.
*
* Contains an adapted version of fs/buffer.c::block_read_full_page().
*/
static
int
ntfs_
file
_read_block
(
struct
page
*
page
)
static
int
ntfs_
attr
_read_block
(
struct
page
*
page
)
{
VCN
vcn
;
LCN
lcn
;
...
...
@@ -119,7 +177,7 @@ static int ntfs_file_read_block(struct page *page)
if
(
!
page_has_buffers
(
page
))
create_empty_buffers
(
page
,
blocksize
,
0
);
bh
=
head
=
page_buffers
(
page
);
if
(
!
bh
)
if
(
unlikely
(
!
bh
)
)
return
-
ENOMEM
;
blocks
=
PAGE_CACHE_SIZE
>>
blocksize_bits
;
...
...
@@ -128,11 +186,9 @@ static int ntfs_file_read_block(struct page *page)
zblock
=
(
ni
->
initialized_size
+
blocksize
-
1
)
>>
blocksize_bits
;
#ifdef DEBUG
if
(
unlikely
(
!
ni
->
mft_no
))
{
ntfs_error
(
vol
->
sb
,
"NTFS: Attempt to access $MFT! This is a "
"very serious bug! Denying access..."
);
return
-
EACCES
;
}
if
(
unlikely
(
!
ni
->
run_list
.
rl
&&
!
ni
->
mft_no
))
panic
(
"NTFS: $MFT/$DATA run list has been unmapped! This is a "
"very serious bug! Cannot continue..."
);
#endif
/* Loop through all the buffers in the page. */
...
...
@@ -211,7 +267,7 @@ static int ntfs_file_read_block(struct page *page)
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
struct
buffer_head
*
tbh
=
arr
[
i
];
lock_buffer
(
tbh
);
tbh
->
b_end_io
=
end_buffer_read_
file
_async
;
tbh
->
b_end_io
=
end_buffer_read_
attr
_async
;
set_buffer_async_read
(
tbh
);
}
/* Finally, start i/o on the buffers. */
...
...
@@ -220,7 +276,7 @@ static int ntfs_file_read_block(struct page *page)
return
0
;
}
/* No i/o was scheduled on any of the buffers. */
if
(
!
PageError
(
page
))
if
(
likely
(
!
PageError
(
page
)
))
SetPageUptodate
(
page
);
else
/* Signal synchronous i/o error. */
nr
=
-
EIO
;
...
...
@@ -234,17 +290,17 @@ static int ntfs_file_read_block(struct page *page)
* @page: page cache page to fill with data
*
* For non-resident attributes, ntfs_file_readpage() fills the @page of the open
* file @file by calling the
generic block_read_full_page() function provided by
*
the kernel which in turn invokes our ntfs_file_get_block() callback in order
*
to create and read
in the buffers associated with the page asynchronously.
* file @file by calling the
ntfs version of the generic block_read_full_page()
*
function provided by the kernel, ntfs_attr_read_block(), which in turn
*
creates and reads
in the buffers associated with the page asynchronously.
*
* For resident attributes, OTOH, ntfs_file_readpage() fills @page by copying
* the data from the mft record (which at this stage is most likely in memory)
* and fills the remainder with zeroes. Thus, in this case I/O is synchronous,
* and fills the remainder with zeroes. Thus, in this case
,
I/O is synchronous,
* as even if the mft record is not cached at this point in time, we need to
* wait for it to be read in before we can do the copy.
*
* Return
zero
on success or -errno on error.
* Return
0
on success or -errno on error.
*/
static
int
ntfs_file_readpage
(
struct
file
*
file
,
struct
page
*
page
)
{
...
...
@@ -256,43 +312,43 @@ static int ntfs_file_readpage(struct file *file, struct page *page)
u32
attr_len
;
int
err
=
0
;
if
(
!
PageLocked
(
page
))
if
(
unlikely
(
!
PageLocked
(
page
)
))
PAGE_BUG
(
page
);
ni
=
NTFS_I
(
page
->
mapping
->
host
);
/* Is the unnamed $DATA attribute resident? */
if
(
test_bit
(
NI_NonResident
,
&
ni
->
state
))
{
if
(
NInoNonResident
(
ni
))
{
/* Attribute is not resident. */
/* If the file is encrypted, we deny access, just like NT4. */
if
(
test_bit
(
NI_Encrypted
,
&
ni
->
state
))
{
if
(
NInoEncrypted
(
ni
))
{
err
=
-
EACCES
;
goto
unl_err_out
;
}
/* Compressed data stream. Handled in compress.c. */
if
(
test_bit
(
NI_Compressed
,
&
ni
->
state
))
if
(
NInoCompressed
(
ni
))
return
ntfs_file_read_compressed_block
(
page
);
/* Normal data stream. */
return
ntfs_
file
_read_block
(
page
);
return
ntfs_
attr
_read_block
(
page
);
}
/* Attribute is resident, implying it is not compressed or encrypted. */
/* Map, pin and lock the mft record for reading. */
mrec
=
map_mft_record
(
READ
,
ni
);
if
(
IS_ERR
(
mrec
))
{
if
(
unlikely
(
IS_ERR
(
mrec
)
))
{
err
=
PTR_ERR
(
mrec
);
goto
unl_err_out
;
}
ctx
=
get_attr_search_ctx
(
ni
,
mrec
);
if
(
!
ctx
)
{
if
(
unlikely
(
!
ctx
)
)
{
err
=
-
ENOMEM
;
goto
unm_unl_err_out
;
}
/* Find the data attribute in the mft record. */
if
(
!
lookup_attr
(
AT_DATA
,
NULL
,
0
,
0
,
0
,
NULL
,
0
,
ctx
))
{
if
(
unlikely
(
!
lookup_attr
(
AT_DATA
,
NULL
,
0
,
0
,
0
,
NULL
,
0
,
ctx
)
))
{
err
=
-
ENOENT
;
goto
put_unm_unl_err_out
;
}
...
...
@@ -330,6 +386,25 @@ static int ntfs_file_readpage(struct file *file, struct page *page)
return
err
;
}
/**
* ntfs_mst_readpage - fill a @page of the mft or a directory with data
* @file: open file/directory to which the @page belongs or NULL
* @page: page cache page to fill with data
*
* Readpage method for the VFS address space operations of directory inodes
* and the $MFT/$DATA attribute.
*
* We just call ntfs_attr_read_block() here, in fact we only need this wrapper
* because of the difference in function parameters.
*/
int
ntfs_mst_readpage
(
struct
file
*
file
,
struct
page
*
page
)
{
if
(
unlikely
(
!
PageLocked
(
page
)))
PAGE_BUG
(
page
);
return
ntfs_attr_read_block
(
page
);
}
/**
* end_buffer_read_mftbmp_async -
*
...
...
@@ -343,7 +418,7 @@ static void end_buffer_read_mftbmp_async(struct buffer_head *bh, int uptodate)
struct
buffer_head
*
tmp
;
struct
page
*
page
;
if
(
uptodate
)
if
(
likely
(
uptodate
)
)
set_buffer_uptodate
(
bh
);
else
clear_buffer_uptodate
(
bh
);
...
...
@@ -386,7 +461,7 @@ static void end_buffer_read_mftbmp_async(struct buffer_head *bh, int uptodate)
}
spin_unlock_irqrestore
(
&
page_uptodate_lock
,
flags
);
if
(
!
PageError
(
page
))
if
(
likely
(
!
PageError
(
page
)
))
SetPageUptodate
(
page
);
unlock_page
(
page
);
return
;
...
...
@@ -410,7 +485,7 @@ static int ntfs_mftbmp_readpage(ntfs_volume *vol, struct page *page)
int
nr
,
i
;
unsigned
char
blocksize_bits
;
if
(
!
PageLocked
(
page
))
if
(
unlikely
(
!
PageLocked
(
page
)
))
PAGE_BUG
(
page
);
blocksize
=
vol
->
sb
->
s_blocksize
;
...
...
@@ -419,7 +494,7 @@ static int ntfs_mftbmp_readpage(ntfs_volume *vol, struct page *page)
if
(
!
page_has_buffers
(
page
))
create_empty_buffers
(
page
,
blocksize
,
0
);
bh
=
head
=
page_buffers
(
page
);
if
(
!
bh
)
if
(
unlikely
(
!
bh
)
)
return
-
ENOMEM
;
blocks
=
PAGE_CACHE_SIZE
>>
blocksize_bits
;
...
...
@@ -503,264 +578,7 @@ static int ntfs_mftbmp_readpage(ntfs_volume *vol, struct page *page)
return
0
;
}
/* No i/o was scheduled on any of the buffers. */
if
(
!
PageError
(
page
))
SetPageUptodate
(
page
);
else
/* Signal synchronous i/o error. */
nr
=
-
EIO
;
unlock_page
(
page
);
return
nr
;
}
/**
* end_buffer_read_mst_async - async io completion for reading index records
* @bh: buffer head on which io is completed
* @uptodate: whether @bh is now uptodate or not
*
* Asynchronous I/O completion handler for reading pages belonging to the
* index allocation attribute address space of directory inodes.
*
* Perform the post read mst fixups when all IO on the page has been completed
* and marks the page uptodate or sets the error bit on the page.
*
* Adapted from fs/buffer.c.
*
* NOTE: We use this function as async io completion handler for reading pages
* belonging to the mft data attribute address space, too as this saves
* duplicating an almost identical function. We do this by cheating a little
* bit in setting the index_block_size in the mft ntfs_inode to the mft record
* size of the volume (vol->mft_record_size), and index_block_size_bits to
* mft_record_size_bits, respectively.
*/
static
void
end_buffer_read_mst_async
(
struct
buffer_head
*
bh
,
int
uptodate
)
{
static
spinlock_t
page_uptodate_lock
=
SPIN_LOCK_UNLOCKED
;
unsigned
long
flags
;
struct
buffer_head
*
tmp
;
struct
page
*
page
;
ntfs_inode
*
ni
;
if
(
uptodate
)
set_buffer_uptodate
(
bh
);
else
clear_buffer_uptodate
(
bh
);
page
=
bh
->
b_page
;
ni
=
NTFS_I
(
page
->
mapping
->
host
);
if
(
likely
(
uptodate
))
{
s64
file_ofs
;
file_ofs
=
(
page
->
index
<<
PAGE_CACHE_SHIFT
)
+
bh_offset
(
bh
);
/* Check for the current buffer head overflowing. */
if
(
file_ofs
+
bh
->
b_size
>
ni
->
initialized_size
)
{
char
*
addr
;
int
ofs
=
0
;
if
(
file_ofs
<
ni
->
initialized_size
)
ofs
=
ni
->
initialized_size
-
file_ofs
;
addr
=
kmap_atomic
(
page
,
KM_BIO_SRC_IRQ
);
memset
(
addr
+
bh_offset
(
bh
)
+
ofs
,
0
,
bh
->
b_size
-
ofs
);
flush_dcache_page
(
page
);
kunmap_atomic
(
addr
,
KM_BIO_SRC_IRQ
);
}
}
else
SetPageError
(
page
);
spin_lock_irqsave
(
&
page_uptodate_lock
,
flags
);
clear_buffer_async_read
(
bh
);
unlock_buffer
(
bh
);
tmp
=
bh
->
b_this_page
;
while
(
tmp
!=
bh
)
{
if
(
buffer_locked
(
tmp
))
{
if
(
buffer_async_read
(
tmp
))
goto
still_busy
;
}
else
if
(
!
buffer_uptodate
(
tmp
))
SetPageError
(
page
);
tmp
=
tmp
->
b_this_page
;
}
spin_unlock_irqrestore
(
&
page_uptodate_lock
,
flags
);
/*
* If none of the buffers had errors then we can set the page uptodate,
* but we first have to perform the post read mst fixups.
*/
if
(
!
PageError
(
page
))
{
char
*
addr
;
unsigned
int
i
,
recs
,
nr_err
=
0
;
u32
rec_size
;
rec_size
=
ni
->
_IDM
(
index_block_size
);
recs
=
PAGE_CACHE_SIZE
/
rec_size
;
addr
=
kmap_atomic
(
page
,
KM_BIO_SRC_IRQ
);
for
(
i
=
0
;
i
<
recs
;
i
++
)
{
if
(
!
post_read_mst_fixup
((
NTFS_RECORD
*
)(
addr
+
i
*
rec_size
),
rec_size
))
continue
;
nr_err
++
;
ntfs_error
(
ni
->
vol
->
sb
,
"post_read_mst_fixup() failed, "
"corrupt %s record 0x%Lx. Run chkdsk."
,
ni
->
mft_no
?
"index"
:
"mft"
,
(
long
long
)((
page
->
index
<<
PAGE_CACHE_SHIFT
>>
ni
->
_IDM
(
index_block_size_bits
))
+
i
));
}
flush_dcache_page
(
page
);
kunmap_atomic
(
addr
,
KM_BIO_SRC_IRQ
);
if
(
likely
(
!
nr_err
&&
recs
))
SetPageUptodate
(
page
);
else
{
ntfs_error
(
ni
->
vol
->
sb
,
"Setting page error, index "
"0x%lx."
,
page
->
index
);
SetPageError
(
page
);
}
}
unlock_page
(
page
);
return
;
still_busy:
spin_unlock_irqrestore
(
&
page_uptodate_lock
,
flags
);
return
;
}
/**
* ntfs_mst_readpage - fill a @page of the mft or a directory with data
* @file: open file/directory to which the page @page belongs or NULL
* @page: page cache page to fill with data
*
* Readpage method for the VFS address space operations.
*
* Fill the page @page of the $MFT or the open directory @dir. We read each
* buffer asynchronously and when all buffers are read in our io completion
* handler end_buffer_read_mst_async() automatically applies the mst fixups to
* the page before finally marking it uptodate and unlocking it.
*
* Contains an adapted version of fs/buffer.c::block_read_full_page().
*/
int
ntfs_mst_readpage
(
struct
file
*
dir
,
struct
page
*
page
)
{
VCN
vcn
;
LCN
lcn
;
ntfs_inode
*
ni
;
ntfs_volume
*
vol
;
struct
buffer_head
*
bh
,
*
head
,
*
arr
[
MAX_BUF_PER_PAGE
];
sector_t
iblock
,
lblock
,
zblock
;
unsigned
int
blocksize
,
blocks
,
vcn_ofs
;
int
i
,
nr
;
unsigned
char
blocksize_bits
;
if
(
!
PageLocked
(
page
))
PAGE_BUG
(
page
);
ni
=
NTFS_I
(
page
->
mapping
->
host
);
vol
=
ni
->
vol
;
blocksize_bits
=
VFS_I
(
ni
)
->
i_blkbits
;
blocksize
=
1
<<
blocksize_bits
;
if
(
!
page_has_buffers
(
page
))
create_empty_buffers
(
page
,
blocksize
,
0
);
bh
=
head
=
page_buffers
(
page
);
if
(
!
bh
)
return
-
ENOMEM
;
blocks
=
PAGE_CACHE_SIZE
>>
blocksize_bits
;
iblock
=
page
->
index
<<
(
PAGE_CACHE_SHIFT
-
blocksize_bits
);
lblock
=
(
ni
->
allocated_size
+
blocksize
-
1
)
>>
blocksize_bits
;
zblock
=
(
ni
->
initialized_size
+
blocksize
-
1
)
>>
blocksize_bits
;
#ifdef DEBUG
if
(
unlikely
(
!
ni
->
run_list
.
rl
&&
!
ni
->
mft_no
))
panic
(
"NTFS: $MFT/$DATA run list has been unmapped! This is a "
"very serious bug! Cannot continue..."
);
#endif
/* Loop through all the buffers in the page. */
nr
=
i
=
0
;
do
{
if
(
unlikely
(
buffer_uptodate
(
bh
)))
continue
;
if
(
unlikely
(
buffer_mapped
(
bh
)))
{
arr
[
nr
++
]
=
bh
;
continue
;
}
bh
->
b_bdev
=
vol
->
sb
->
s_bdev
;
/* Is the block within the allowed limits? */
if
(
iblock
<
lblock
)
{
BOOL
is_retry
=
FALSE
;
/* Convert iblock into corresponding vcn and offset. */
vcn
=
(
VCN
)
iblock
<<
blocksize_bits
>>
vol
->
cluster_size_bits
;
vcn_ofs
=
((
VCN
)
iblock
<<
blocksize_bits
)
&
vol
->
cluster_size_mask
;
retry_remap:
/* Convert the vcn to the corresponding lcn. */
down_read
(
&
ni
->
run_list
.
lock
);
lcn
=
vcn_to_lcn
(
ni
->
run_list
.
rl
,
vcn
);
up_read
(
&
ni
->
run_list
.
lock
);
/* Successful remap. */
if
(
lcn
>=
0
)
{
/* Setup buffer head to correct block. */
bh
->
b_blocknr
=
((
lcn
<<
vol
->
cluster_size_bits
)
+
vcn_ofs
)
>>
blocksize_bits
;
set_buffer_mapped
(
bh
);
/* Only read initialized data blocks. */
if
(
iblock
<
zblock
)
{
arr
[
nr
++
]
=
bh
;
continue
;
}
/* Fully non-initialized data block, zero it. */
goto
handle_zblock
;
}
/* It is a hole, need to zero it. */
if
(
lcn
==
LCN_HOLE
)
goto
handle_hole
;
/* If first try and run list unmapped, map and retry. */
if
(
!
is_retry
&&
lcn
==
LCN_RL_NOT_MAPPED
)
{
is_retry
=
TRUE
;
if
(
!
map_run_list
(
ni
,
vcn
))
goto
retry_remap
;
}
/* Hard error, zero out region. */
SetPageError
(
page
);
ntfs_error
(
vol
->
sb
,
"vcn_to_lcn(vcn = 0x%Lx) failed "
"with error code 0x%Lx%s."
,
(
long
long
)
vcn
,
(
long
long
)
-
lcn
,
is_retry
?
" even after retrying"
:
""
);
// FIXME: Depending on vol->on_errors, do something.
}
/*
* Either iblock was outside lblock limits or vcn_to_lcn()
* returned error. Just zero that portion of the page and set
* the buffer uptodate.
*/
handle_hole:
bh
->
b_blocknr
=
-
1UL
;
clear_buffer_mapped
(
bh
);
handle_zblock:
memset
(
kmap
(
page
)
+
i
*
blocksize
,
0
,
blocksize
);
flush_dcache_page
(
page
);
kunmap
(
page
);
set_buffer_uptodate
(
bh
);
}
while
(
i
++
,
iblock
++
,
(
bh
=
bh
->
b_this_page
)
!=
head
);
/* Check we have at least one buffer ready for i/o. */
if
(
nr
)
{
/* Lock the buffers. */
for
(
i
=
0
;
i
<
nr
;
i
++
)
{
struct
buffer_head
*
tbh
=
arr
[
i
];
lock_buffer
(
tbh
);
tbh
->
b_end_io
=
end_buffer_read_mst_async
;
set_buffer_async_read
(
tbh
);
}
/* Finally, start i/o on the buffers. */
for
(
i
=
0
;
i
<
nr
;
i
++
)
submit_bh
(
READ
,
arr
[
i
]);
return
0
;
}
/* No i/o was scheduled on any of the buffers. */
if
(
!
PageError
(
page
))
if
(
likely
(
!
PageError
(
page
)))
SetPageUptodate
(
page
);
else
/* Signal synchronous i/o error. */
nr
=
-
EIO
;
...
...
fs/ntfs/dir.c
View file @
7403ed3e
...
...
@@ -27,7 +27,7 @@
/**
* The little endian Unicode string $I30 as a global constant.
*/
const
uchar_t
I30
[
5
]
=
{
const_cpu_to_le16
(
'$'
),
const_cpu_to_le16
(
'I'
),
uchar_t
I30
[
5
]
=
{
const_cpu_to_le16
(
'$'
),
const_cpu_to_le16
(
'I'
),
const_cpu_to_le16
(
'3'
),
const_cpu_to_le16
(
'0'
),
const_cpu_to_le16
(
0
)
};
...
...
fs/ntfs/dir.h
View file @
7403ed3e
...
...
@@ -38,7 +38,7 @@ typedef struct {
}
__attribute__
((
__packed__
))
ntfs_name
;
/* The little endian Unicode string $I30 as a global constant. */
extern
const
uchar_t
I30
[
5
];
extern
uchar_t
I30
[
5
];
extern
MFT_REF
ntfs_lookup_inode_by_name
(
ntfs_inode
*
dir_ni
,
const
uchar_t
*
uname
,
const
int
uname_len
,
ntfs_name
**
res
);
...
...
fs/ntfs/inode.c
View file @
7403ed3e
...
...
@@ -24,6 +24,178 @@
#include "ntfs.h"
#include "dir.h"
#include "inode.h"
#include "attrib.h"
/**
* ntfs_attr - ntfs in memory attribute structure
* @mft_no: mft record number of the base mft record of this attribute
* @name: Unicode name of the attribute (NULL if unnamed)
* @name_len: length of @name in Unicode characters (0 if unnamed)
* @type: attribute type (see layout.h)
*
* This structure exists only to provide a small structure for the
* ntfs_iget()/ntfs_test_inode()/ntfs_init_locked_inode() mechanism.
*
* NOTE: Elements are ordered by size to make the structure as compact as
* possible on all architectures.
*/
typedef
struct
{
unsigned
long
mft_no
;
uchar_t
*
name
;
u32
name_len
;
ATTR_TYPES
type
;
}
ntfs_attr
;
/**
* ntfs_test_inode - compare two (possibly fake) inodes for equality
* @vi: vfs inode which to test
* @na: ntfs attribute which is being tested with
*
* Compare the ntfs attribute embedded in the ntfs specific part of the vfs
* inode @vi for equality with the ntfs attribute @na.
*
* If searching for the normal file/directory inode, set @na->type to AT_UNUSED.
* @na->name and @na->name_len are then ignored.
*
* Return 1 if the attributes match and 0 if not.
*
* NOTE: This function runs with the inode_lock spin lock held so it is not
* allowed to sleep.
*/
static
int
ntfs_test_inode
(
struct
inode
*
vi
,
ntfs_attr
*
na
)
{
ntfs_inode
*
ni
;
if
(
vi
->
i_ino
!=
na
->
mft_no
)
return
0
;
ni
=
NTFS_I
(
vi
);
/* If !NInoAttr(ni), @vi is a normal file or directory inode. */
if
(
likely
(
!
NInoAttr
(
ni
)))
{
/* If not looking for a normal inode this is a mismatch. */
if
(
unlikely
(
na
->
type
!=
AT_UNUSED
))
return
0
;
}
else
{
/* A fake inode describing an attribute. */
if
(
ni
->
type
!=
na
->
type
)
return
0
;
if
(
ni
->
name_len
!=
na
->
name_len
)
return
0
;
if
(
na
->
name_len
&&
memcmp
(
ni
->
name
,
na
->
name
,
na
->
name_len
*
sizeof
(
uchar_t
)))
return
0
;
}
/* Match! */
return
1
;
}
/**
* ntfs_init_locked_inode - initialize an inode
* @vi: vfs inode to initialize
* @na: ntfs attribute which to initialize @vi to
*
* Initialize the vfs inode @vi with the values from the ntfs attribute @na in
* order to enable ntfs_test_inode() to do its work.
*
* If initializing the normal file/directory inode, set @na->type to AT_UNUSED.
* In that case, @na->name and @na->name_len should be set to NULL and 0,
* respectively. Although that is not strictly necessary as
* ntfs_read_inode_locked() will fill them in later.
*
* Return 0 on success and -errno on error.
*
* NOTE: This function runs with the inode_lock spin lock held so it is not
* allowed to sleep. (Hence the GFP_ATOMIC allocation.)
*/
static
int
ntfs_init_locked_inode
(
struct
inode
*
vi
,
ntfs_attr
*
na
)
{
ntfs_inode
*
ni
=
NTFS_I
(
vi
);
vi
->
i_ino
=
na
->
mft_no
;
ni
->
type
=
na
->
type
;
ni
->
name
=
na
->
name
;
ni
->
name_len
=
na
->
name_len
;
/* If initializing a normal inode, we are done. */
if
(
likely
(
na
->
type
==
AT_UNUSED
))
return
0
;
/* It is a fake inode. */
NInoSetAttr
(
ni
);
/*
* We have I30 global constant as an optimization as it is the name
* in >99.9% of named attributes! The other <0.1% incur a GFP_ATOMIC
* allocation but that is ok. And most attributes are unnamed anyway,
* thus the fraction of named attributes with name != I30 is actually
* absolutely tiny.
*/
if
(
na
->
name
&&
na
->
name_len
&&
na
->
name
!=
I30
)
{
unsigned
int
i
;
i
=
na
->
name_len
*
sizeof
(
uchar_t
);
ni
->
name
=
(
uchar_t
*
)
kmalloc
(
i
+
sizeof
(
uchar_t
),
GFP_ATOMIC
);
if
(
!
ni
->
name
)
return
-
ENOMEM
;
memcpy
(
ni
->
name
,
na
->
name
,
i
);
ni
->
name
[
i
]
=
cpu_to_le16
(
'\0'
);
}
return
0
;
}
typedef
int
(
*
test_t
)(
struct
inode
*
,
void
*
);
typedef
int
(
*
set_t
)(
struct
inode
*
,
void
*
);
static
void
ntfs_read_locked_inode
(
struct
inode
*
vi
);
/**
* ntfs_iget - obtain a struct inode corresponding to a specific normal inode
* @sb: super block of mounted volume
* @mft_no: mft record number / inode number to obtain
*
* Obtain the struct inode corresponding to a specific normal inode (i.e. a
* file or directory).
*
* If the inode is in the cache, it is just returned with an increased
* reference count. Otherwise, a new struct inode is allocated and initialized,
* and finally ntfs_read_locked_inode() is called to read in the inode and
* fill in the remainder of the inode structure.
*
* Return the struct inode on success. Check the return value with IS_ERR() and
* if true, the function failed and the error code is obtained from PTR_ERR().
*/
struct
inode
*
ntfs_iget
(
struct
super_block
*
sb
,
unsigned
long
mft_no
)
{
struct
inode
*
vi
;
ntfs_attr
na
;
na
.
mft_no
=
mft_no
;
na
.
type
=
AT_UNUSED
;
na
.
name
=
NULL
;
na
.
name_len
=
0
;
vi
=
iget5_locked
(
sb
,
mft_no
,
(
test_t
)
ntfs_test_inode
,
(
set_t
)
ntfs_init_locked_inode
,
&
na
);
if
(
!
vi
)
return
ERR_PTR
(
-
ENOMEM
);
/* If this is a freshly allocated inode, need to read it now. */
if
(
vi
->
i_state
&
I_NEW
)
{
ntfs_read_locked_inode
(
vi
);
unlock_new_inode
(
vi
);
}
#if 0
// TODO: Enable this and do the follow up cleanup, i.e. remove all the
// bad inode checks. -- BUT: Do we actually want to do this? -- It may
// result in repeated attemps to read a bad inode which is not
// desirable. (AIA)
/*
* There is no point in keeping bad inodes around. This also simplifies
* things in that we never need to check for bad inodes elsewhere.
*/
if (is_bad_inode(vi)) {
iput(vi);
vi = ERR_PTR(-EIO);
}
#endif
return
vi
;
}
struct
inode
*
ntfs_alloc_big_inode
(
struct
super_block
*
sb
)
{
...
...
@@ -32,12 +204,12 @@ struct inode *ntfs_alloc_big_inode(struct super_block *sb)
ntfs_debug
(
"Entering."
);
ni
=
(
ntfs_inode
*
)
kmem_cache_alloc
(
ntfs_big_inode_cache
,
SLAB_NOFS
);
if
(
!
ni
)
{
ntfs_error
(
sb
,
"Allocation of NTFS big inode structure "
"failed."
);
return
NULL
;
}
if
(
likely
(
ni
!=
NULL
))
{
ni
->
state
=
0
;
return
VFS_I
(
ni
);
}
ntfs_error
(
sb
,
"Allocation of NTFS big inode structure failed."
);
return
NULL
;
}
void
ntfs_destroy_big_inode
(
struct
inode
*
inode
)
...
...
@@ -49,17 +221,20 @@ void ntfs_destroy_big_inode(struct inode *inode)
kmem_cache_free
(
ntfs_big_inode_cache
,
NTFS_I
(
inode
));
}
ntfs_inode
*
ntfs_alloc
_inode
(
void
)
static
ntfs_inode
*
ntfs_alloc_extent
_inode
(
void
)
{
ntfs_inode
*
ni
=
(
ntfs_inode
*
)
kmem_cache_alloc
(
ntfs_inode_cache
,
SLAB_NOFS
);
ntfs_debug
(
"Entering."
);
if
(
unlikely
(
!
ni
))
n
tfs_error
(
NULL
,
"Allocation of NTFS inode structure failed."
)
;
if
(
likely
(
ni
!=
NULL
))
{
n
i
->
state
=
0
;
return
ni
;
}
ntfs_error
(
NULL
,
"Allocation of NTFS inode structure failed."
);
return
NULL
;
}
void
ntfs_destroy_inode
(
ntfs_inode
*
ni
)
void
ntfs_destroy_
extent_
inode
(
ntfs_inode
*
ni
)
{
ntfs_debug
(
"Entering."
);
BUG_ON
(
atomic_read
(
&
ni
->
mft_count
)
||
!
atomic_dec_and_test
(
&
ni
->
count
));
...
...
@@ -68,27 +243,42 @@ void ntfs_destroy_inode(ntfs_inode *ni)
/**
* __ntfs_init_inode - initialize ntfs specific part of an inode
* @sb: super block of mounted volume
* @ni: freshly allocated ntfs inode which to initialize
*
* Initialize an ntfs inode to defaults.
*
* NOTE: ni->mft_no, ni->state, ni->type, ni->name, and ni->name_len are left
* untouched. Make sure to initialize them elsewhere.
*
* Return zero on success and -ENOMEM on error.
*/
static
void
__ntfs_init_inode
(
struct
super_block
*
sb
,
ntfs_inode
*
ni
)
{
ntfs_debug
(
"Entering."
);
memset
(
ni
,
0
,
sizeof
(
ntfs_inode
));
ni
->
initialized_size
=
ni
->
allocated_size
=
0
;
ni
->
seq_no
=
0
;
atomic_set
(
&
ni
->
count
,
1
);
ni
->
vol
=
N
ULL
;
ni
->
vol
=
N
TFS_SB
(
sb
)
;
init_run_list
(
&
ni
->
run_list
);
init_rwsem
(
&
ni
->
mrec_lock
);
atomic_set
(
&
ni
->
mft_count
,
0
);
ni
->
page
=
NULL
;
ni
->
page_ofs
=
0
;
ni
->
attr_list_size
=
0
;
ni
->
attr_list
=
NULL
;
init_run_list
(
&
ni
->
attr_list_rl
);
ni
->
_IDM
(
index_block_size
)
=
0
;
ni
->
_IDM
(
index_vcn_size
)
=
0
;
ni
->
_IDM
(
bmp_size
)
=
0
;
ni
->
_IDM
(
bmp_initialized_size
)
=
0
;
ni
->
_IDM
(
bmp_allocated_size
)
=
0
;
init_run_list
(
&
ni
->
_IDM
(
bmp_rl
));
ni
->
_IDM
(
index_block_size_bits
)
=
0
;
ni
->
_IDM
(
index_vcn_size_bits
)
=
0
;
init_MUTEX
(
&
ni
->
extent_lock
);
ni
->
nr_extents
=
0
;
ni
->
_INE
(
base_ntfs_ino
)
=
NULL
;
ni
->
vol
=
NTFS_SB
(
sb
);
return
;
}
...
...
@@ -102,13 +292,18 @@ static void ntfs_init_big_inode(struct inode *vi)
return
;
}
ntfs_inode
*
ntfs_new_
inode
(
struct
super_block
*
sb
)
ntfs_inode
*
ntfs_new_
extent_inode
(
struct
super_block
*
sb
,
unsigned
long
mft_no
)
{
ntfs_inode
*
ni
=
ntfs_alloc_inode
();
ntfs_inode
*
ni
=
ntfs_alloc_
extent_
inode
();
ntfs_debug
(
"Entering."
);
if
(
ni
)
if
(
likely
(
ni
!=
NULL
))
{
__ntfs_init_inode
(
sb
,
ni
);
ni
->
mft_no
=
mft_no
;
ni
->
type
=
AT_UNUSED
;
ni
->
name
=
NULL
;
ni
->
name_len
=
0
;
}
return
ni
;
}
...
...
@@ -189,18 +384,20 @@ static int ntfs_is_extended_system_file(attr_search_context *ctx)
}
/**
* ntfs_read_inode - read an inode from its device
* ntfs_read_
locked_
inode - read an inode from its device
* @vi: inode to read
*
* ntfs_read_
inode() is called from the VFS iget() function
to read the inode
* ntfs_read_
locked_inode() is called from the ntfs_iget()
to read the inode
* described by @vi into memory from the device.
*
* The only fields in @vi that we need to/can look at when the function is
* called are i_sb, pointing to the mounted device's super block, and i_ino,
* the number of the inode to load.
* the number of the inode to load. If this is a fake inode, i.e. NInoAttr(),
* then the fields type, name, and name_len are also valid, and describe the
* attribute which this fake inode represents.
*
* ntfs_read_
inode() maps, pins and locks the mft record number i_ino for
* reading and sets up the necessary @vi fields as well as initializing
* ntfs_read_
locked_inode() maps, pins and locks the mft record number i_ino
*
for
reading and sets up the necessary @vi fields as well as initializing
* the ntfs inode.
*
* Q: What locks are held when the function is called?
...
...
@@ -209,9 +406,9 @@ static int ntfs_is_extended_system_file(attr_search_context *ctx)
* i_flags is set to 0 and we have no business touching it. Only an ioctl()
* is allowed to write to them. We should of course be honouring them but
* we need to do that using the IS_* macros defined in include/linux/fs.h.
* In any case ntfs_read_
inode() has nothing to do with i_flags at all
.
* In any case ntfs_read_
locked_inode() has nothing to do with i_flags
.
*/
void
ntfs_rea
d_inode
(
struct
inode
*
vi
)
static
void
ntfs_read_locke
d_inode
(
struct
inode
*
vi
)
{
ntfs_volume
*
vol
=
NTFS_SB
(
vi
->
i_sb
);
ntfs_inode
*
ni
;
...
...
@@ -239,7 +436,8 @@ void ntfs_read_inode(struct inode *vi)
/*
* Initialize the ntfs specific part of @vi special casing
* FILE_MFT which we need to do at mount time.
* FILE_MFT which we need to do at mount time. This also sets
* ni->mft_no to vi->i_ino.
*/
if
(
vi
->
i_ino
!=
FILE_MFT
)
ntfs_init_big_inode
(
vi
);
...
...
@@ -358,13 +556,14 @@ void ntfs_read_inode(struct inode *vi)
if
(
vi
->
i_ino
==
FILE_MFT
)
goto
skip_attr_list_load
;
ntfs_debug
(
"Attribute list found in inode 0x%lx."
,
vi
->
i_ino
);
ni
->
state
|=
1
<<
NI_AttrList
;
NInoSetAttrList
(
ni
)
;
if
(
ctx
->
attr
->
flags
&
ATTR_IS_ENCRYPTED
||
ctx
->
attr
->
flags
&
ATTR_COMPRESSION_MASK
)
{
ctx
->
attr
->
flags
&
ATTR_COMPRESSION_MASK
||
ctx
->
attr
->
flags
&
ATTR_IS_SPARSE
)
{
ntfs_error
(
vi
->
i_sb
,
"Attribute list attribute is "
"compressed/encrypted
. Not allowed.
"
"
Corrupt inode. You should run
"
"chkdsk."
);
"compressed/encrypted
/sparse. Not
"
"
allowed. Corrupt inode. You should
"
"
run
chkdsk."
);
goto
put_unm_err_out
;
}
/* Now allocate memory for the attribute list. */
...
...
@@ -377,7 +576,7 @@ void ntfs_read_inode(struct inode *vi)
goto
ec_put_unm_err_out
;
}
if
(
ctx
->
attr
->
non_resident
)
{
ni
->
state
|=
1
<<
NI_AttrListNonResident
;
NInoSetAttrListNonResident
(
ni
)
;
if
(
ctx
->
attr
->
_ANR
(
lowest_vcn
))
{
ntfs_error
(
vi
->
i_sb
,
"Attribute list has non "
"zero lowest_vcn. Inode is "
...
...
@@ -459,7 +658,7 @@ void ntfs_read_inode(struct inode *vi)
* encrypted.
*/
if
(
ctx
->
attr
->
flags
&
ATTR_COMPRESSION_MASK
)
ni
->
state
|=
1
<<
NI_Compressed
;
NInoSetCompressed
(
ni
)
;
if
(
ctx
->
attr
->
flags
&
ATTR_IS_ENCRYPTED
)
{
if
(
ctx
->
attr
->
flags
&
ATTR_COMPRESSION_MASK
)
{
ntfs_error
(
vi
->
i_sb
,
"Found encrypted and "
...
...
@@ -467,8 +666,10 @@ void ntfs_read_inode(struct inode *vi)
"allowed."
);
goto
put_unm_err_out
;
}
ni
->
state
|=
1
<<
NI_Encrypted
;
NInoSetEncrypted
(
ni
)
;
}
if
(
ctx
->
attr
->
flags
&
ATTR_IS_SPARSE
)
NInoSetSparse
(
ni
);
ir
=
(
INDEX_ROOT
*
)((
char
*
)
ctx
->
attr
+
le16_to_cpu
(
ctx
->
attr
->
_ARA
(
value_offset
)));
ir_end
=
(
char
*
)
ir
+
le32_to_cpu
(
ctx
->
attr
->
_ARA
(
value_length
));
...
...
@@ -530,12 +731,19 @@ void ntfs_read_inode(struct inode *vi)
ni
->
_IDM
(
index_vcn_size
)
=
vol
->
sector_size
;
ni
->
_IDM
(
index_vcn_size_bits
)
=
vol
->
sector_size_bits
;
}
/* Setup the index allocation attribute, even if not present. */
NInoSetMstProtected
(
ni
);
ni
->
type
=
AT_INDEX_ALLOCATION
;
ni
->
name
=
I30
;
ni
->
name_len
=
4
;
if
(
!
(
ir
->
index
.
flags
&
LARGE_INDEX
))
{
/* No index allocation. */
vi
->
i_size
=
ni
->
initialized_size
=
0
;
goto
skip_large_dir_stuff
;
}
/* LARGE_INDEX: Index allocation present. Setup state. */
ni
->
state
|=
1
<<
NI_NonResident
;
NInoSetIndexAllocPresent
(
ni
)
;
/* Find index allocation attribute. */
reinit_attr_search_ctx
(
ctx
);
if
(
!
lookup_attr
(
AT_INDEX_ALLOCATION
,
I30
,
4
,
CASE_SENSITIVE
,
...
...
@@ -555,6 +763,11 @@ void ntfs_read_inode(struct inode *vi)
"is encrypted."
);
goto
put_unm_err_out
;
}
if
(
ctx
->
attr
->
flags
&
ATTR_IS_SPARSE
)
{
ntfs_error
(
vi
->
i_sb
,
"$INDEX_ALLOCATION attribute "
"is sparse."
);
goto
put_unm_err_out
;
}
if
(
ctx
->
attr
->
flags
&
ATTR_COMPRESSION_MASK
)
{
ntfs_error
(
vi
->
i_sb
,
"$INDEX_ALLOCATION attribute "
"is compressed."
);
...
...
@@ -581,13 +794,13 @@ void ntfs_read_inode(struct inode *vi)
goto
put_unm_err_out
;
}
if
(
ctx
->
attr
->
flags
&
(
ATTR_COMPRESSION_MASK
|
ATTR_IS_ENCRYPTED
))
{
ATTR_IS_ENCRYPTED
|
ATTR_IS_SPARSE
))
{
ntfs_error
(
vi
->
i_sb
,
"$BITMAP attribute is compressed "
"and/or encrypted."
);
"and/or encrypted
and/or sparse
."
);
goto
put_unm_err_out
;
}
if
(
ctx
->
attr
->
non_resident
)
{
ni
->
state
|=
1
<<
NI_BmpNonResident
;
NInoSetBmpNonResident
(
ni
)
;
if
(
ctx
->
attr
->
_ANR
(
lowest_vcn
))
{
ntfs_error
(
vi
->
i_sb
,
"First extent of $BITMAP "
"attribute has non zero "
...
...
@@ -645,8 +858,15 @@ void ntfs_read_inode(struct inode *vi)
vi
->
i_fop
=
&
ntfs_dir_ops
;
vi
->
i_mapping
->
a_ops
=
&
ntfs_dir_aops
;
}
else
{
/* It is a file
: find first extent of unnamed data attribute
. */
/* It is a file. */
reinit_attr_search_ctx
(
ctx
);
/* Setup the data attribute, even if not present. */
ni
->
type
=
AT_DATA
;
ni
->
name
=
NULL
;
ni
->
name_len
=
0
;
/* Find first extent of the unnamed data attribute. */
if
(
!
lookup_attr
(
AT_DATA
,
NULL
,
0
,
0
,
0
,
NULL
,
0
,
ctx
))
{
vi
->
i_size
=
ni
->
initialized_size
=
ni
->
allocated_size
=
0LL
;
...
...
@@ -675,9 +895,9 @@ void ntfs_read_inode(struct inode *vi)
}
/* Setup the state. */
if
(
ctx
->
attr
->
non_resident
)
{
ni
->
state
|=
1
<<
NI_NonResident
;
NInoSetNonResident
(
ni
)
;
if
(
ctx
->
attr
->
flags
&
ATTR_COMPRESSION_MASK
)
{
ni
->
state
|=
1
<<
NI_Compressed
;
NInoSetCompressed
(
ni
)
;
if
(
vol
->
cluster_size
>
4096
)
{
ntfs_error
(
vi
->
i_sb
,
"Found "
"compressed data but "
...
...
@@ -707,8 +927,9 @@ void ntfs_read_inode(struct inode *vi)
goto
ec_put_unm_err_out
;
}
ni
->
_ICF
(
compression_block_size
)
=
1U
<<
(
ctx
->
attr
->
_ANR
(
compression_unit
)
+
vol
->
cluster_size_bits
);
ctx
->
attr
->
_ANR
(
compression_unit
)
+
vol
->
cluster_size_bits
);
ni
->
_ICF
(
compression_block_size_bits
)
=
ffs
(
ni
->
_ICF
(
compression_block_size
))
-
1
;
}
...
...
@@ -718,8 +939,10 @@ void ntfs_read_inode(struct inode *vi)
"and compressed data."
);
goto
put_unm_err_out
;
}
ni
->
state
|=
1
<<
NI_Encrypted
;
NInoSetEncrypted
(
ni
)
;
}
if
(
ctx
->
attr
->
flags
&
ATTR_IS_SPARSE
)
NInoSetSparse
(
ni
);
if
(
ctx
->
attr
->
_ANR
(
lowest_vcn
))
{
ntfs_error
(
vi
->
i_sb
,
"First extent of $DATA "
"attribute has non zero "
...
...
@@ -852,15 +1075,24 @@ void ntfs_read_inode_mount(struct inode *vi)
ntfs_debug
(
"Entering."
);
/* Initialize the ntfs specific part of @vi. */
ntfs_init_big_inode
(
vi
);
ni
=
NTFS_I
(
vi
);
if
(
vi
->
i_ino
!=
FILE_MFT
)
{
ntfs_error
(
sb
,
"Called for inode 0x%lx but only inode %d "
"allowed."
,
vi
->
i_ino
,
FILE_MFT
);
goto
err_out
;
}
/* Initialize the ntfs specific part of @vi. */
ntfs_init_big_inode
(
vi
);
ni
=
NTFS_I
(
vi
);
/* Setup the data attribute. It is special as it is mst protected. */
NInoSetNonResident
(
ni
);
NInoSetMstProtected
(
ni
);
ni
->
type
=
AT_DATA
;
ni
->
name
=
NULL
;
ni
->
name_len
=
0
;
/*
* This sets up our little cheat allowing us to reuse the async io
* completion handler for directories.
...
...
@@ -930,13 +1162,14 @@ void ntfs_read_inode_mount(struct inode *vi)
u8
*
al_end
;
ntfs_debug
(
"Attribute list attribute found in $MFT."
);
ni
->
state
|=
1
<<
NI_AttrList
;
NInoSetAttrList
(
ni
)
;
if
(
ctx
->
attr
->
flags
&
ATTR_IS_ENCRYPTED
||
ctx
->
attr
->
flags
&
ATTR_COMPRESSION_MASK
)
{
ctx
->
attr
->
flags
&
ATTR_COMPRESSION_MASK
||
ctx
->
attr
->
flags
&
ATTR_IS_SPARSE
)
{
ntfs_error
(
sb
,
"Attribute list attribute is "
"compressed/encrypted
. Not allowed.
"
"
$MFT is corrupt. You should run
"
"chkdsk."
);
"compressed/encrypted
/sparse. Not
"
"
allowed. $MFT is corrupt. You should
"
"
run
chkdsk."
);
goto
put_err_out
;
}
/* Now allocate memory for the attribute list. */
...
...
@@ -948,7 +1181,7 @@ void ntfs_read_inode_mount(struct inode *vi)
goto
put_err_out
;
}
if
(
ctx
->
attr
->
non_resident
)
{
ni
->
state
|=
1
<<
NI_AttrListNonResident
;
NInoSetAttrListNonResident
(
ni
)
;
if
(
ctx
->
attr
->
_ANR
(
lowest_vcn
))
{
ntfs_error
(
sb
,
"Attribute list has non zero "
"lowest_vcn. $MFT is corrupt. "
...
...
@@ -1071,11 +1304,13 @@ void ntfs_read_inode_mount(struct inode *vi)
}
/* $MFT must be uncompressed and unencrypted. */
if
(
attr
->
flags
&
ATTR_COMPRESSION_MASK
||
attr
->
flags
&
ATTR_IS_ENCRYPTED
)
{
ntfs_error
(
sb
,
"$MFT must be uncompressed and "
"unencrypted but a compressed/"
"encrypted extent was found. "
"$MFT is corrupt. Run chkdsk."
);
attr
->
flags
&
ATTR_IS_ENCRYPTED
||
attr
->
flags
&
ATTR_IS_SPARSE
)
{
ntfs_error
(
sb
,
"$MFT must be uncompressed, "
"non-sparse, and unencrypted but a "
"compressed/sparse/encrypted extent "
"was found. $MFT is corrupt. Run "
"chkdsk."
);
goto
put_err_out
;
}
/*
...
...
@@ -1123,7 +1358,7 @@ void ntfs_read_inode_mount(struct inode *vi)
ntfs_error
(
sb
,
"$MFT is too big! Aborting."
);
goto
put_err_out
;
}
vol
->
_VMM
(
nr_mft_records
)
=
ll
;
vol
->
nr_mft_records
=
ll
;
/*
* We have got the first extent of the run_list for
* $MFT which means it is now relatively safe to call
...
...
@@ -1149,7 +1384,7 @@ void ntfs_read_inode_mount(struct inode *vi)
* ntfs_read_inode() on extents of $MFT/$DATA. But lets
* hope this never happens...
*/
ntfs_read_inode
(
vi
);
ntfs_read_
locked_
inode
(
vi
);
if
(
is_bad_inode
(
vi
))
{
ntfs_error
(
sb
,
"ntfs_read_inode() of $MFT "
"failed. BUG or corrupt $MFT. "
...
...
@@ -1296,29 +1531,42 @@ void __ntfs_clear_inode(ntfs_inode *ni)
// FIXME: Handle dirty case for each extent inode!
for
(
i
=
0
;
i
<
ni
->
nr_extents
;
i
++
)
ntfs_
destroy
_inode
(
ni
->
_INE
(
extent_ntfs_inos
)[
i
]);
ntfs_
clear_extent
_inode
(
ni
->
_INE
(
extent_ntfs_inos
)[
i
]);
kfree
(
ni
->
_INE
(
extent_ntfs_inos
));
}
/* Free all alocated memory. */
down_write
(
&
ni
->
run_list
.
lock
);
if
(
ni
->
run_list
.
rl
)
{
ntfs_free
(
ni
->
run_list
.
rl
);
ni
->
run_list
.
rl
=
NULL
;
}
up_write
(
&
ni
->
run_list
.
lock
);
if
(
ni
->
attr_list
)
{
ntfs_free
(
ni
->
attr_list
);
ni
->
attr_list
=
NULL
;
}
down_write
(
&
ni
->
attr_list_rl
.
lock
);
if
(
ni
->
attr_list_rl
.
rl
)
{
ntfs_free
(
ni
->
attr_list_rl
.
rl
);
ni
->
attr_list_rl
.
rl
=
NULL
;
}
up_write
(
&
ni
->
attr_list_rl
.
lock
);
if
(
ni
->
name_len
&&
ni
->
name
!=
I30
)
{
/* Catch bugs... */
BUG_ON
(
!
ni
->
name
);
kfree
(
ni
->
name
);
}
}
void
ntfs_clear_inode
(
ntfs_inode
*
ni
)
void
ntfs_clear_
extent_
inode
(
ntfs_inode
*
ni
)
{
__ntfs_clear_inode
(
ni
);
/* Bye, bye... */
ntfs_destroy_inode
(
ni
);
ntfs_destroy_
extent_
inode
(
ni
);
}
/**
...
...
@@ -1339,6 +1587,7 @@ void ntfs_clear_big_inode(struct inode *vi)
if
(
S_ISDIR
(
vi
->
i_mode
))
{
down_write
(
&
ni
->
_IDM
(
bmp_rl
).
lock
);
if
(
ni
->
_IDM
(
bmp_rl
).
rl
)
ntfs_free
(
ni
->
_IDM
(
bmp_rl
).
rl
);
up_write
(
&
ni
->
_IDM
(
bmp_rl
).
lock
);
}
...
...
fs/ntfs/inode.h
View file @
7403ed3e
...
...
@@ -3,7 +3,7 @@
* the Linux-NTFS project.
*
* Copyright (c) 2001,2002 Anton Altaparmakov.
* Copyright (
C
) 2002 Richard Russon.
* Copyright (
c
) 2002 Richard Russon.
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
...
...
@@ -26,6 +26,7 @@
#include <linux/seq_file.h>
#include "layout.h"
#include "volume.h"
typedef
struct
_ntfs_inode
ntfs_inode
;
...
...
@@ -38,21 +39,39 @@ struct _ntfs_inode {
s64
initialized_size
;
/* Copy from $DATA/$INDEX_ALLOCATION. */
s64
allocated_size
;
/* Copy from $DATA/$INDEX_ALLOCATION. */
unsigned
long
state
;
/* NTFS specific flags describing this inode.
See
fs/ntfs/ntfs.h:ntfs_inode_state_bits
. */
See
ntfs_inode_state_bits below
. */
unsigned
long
mft_no
;
/* Number of the mft record / inode. */
u16
seq_no
;
/* Sequence number of the mft record. */
atomic_t
count
;
/* Inode reference count for book keeping. */
ntfs_volume
*
vol
;
/* Pointer to the ntfs volume of this inode. */
/*
* If NInoAttr() is true, the below fields describe the attribute which
* this fake inode belongs to. The actual inode of this attribute is
* pointed to by base_ntfs_ino and nr_extents is always set to -1 (see
* below). For real inodes, we also set the type (AT_DATA for files and
* AT_INDEX_ALLOCATION for directories), with the name = NULL and
* name_len = 0 for files and name = I30 (global constant) and
* name_len = 4 for directories.
*/
ATTR_TYPES
type
;
/* Attribute type of this fake inode. */
uchar_t
*
name
;
/* Attribute name of this fake inode. */
u32
name_len
;
/* Attribute name length of this fake inode. */
run_list
run_list
;
/* If state has the NI_NonResident bit set,
the run list of the unnamed data attribute
(if a file) or of the index allocation
attribute (directory). If run_list.rl is
NULL, the run list has not been read in or
has been unmapped. If NI_NonResident is
clear, the unnamed data attribute is
resident (file) or there is no $I30 index
allocation attribute (directory). In that
case run_list.rl is always NULL.*/
attribute (directory) or of the attribute
described by the fake inode (if NInoAttr()).
If run_list.rl is NULL, the run list has not
been read in yet or has been unmapped. If
NI_NonResident is clear, the attribute is
resident (file and fake inode) or there is
no $I30 index allocation attribute
(small directory). In the latter case
run_list.rl is always NULL.*/
/*
* The following fields are only valid for real inodes and extent
* inodes.
*/
struct
rw_semaphore
mrec_lock
;
/* Lock for serializing access to the
mft record belonging to this inode. */
atomic_t
mft_count
;
/* Mapping reference count for book keeping. */
...
...
@@ -74,17 +93,18 @@ struct _ntfs_inode {
union
{
struct
{
/* It is a directory or $MFT. */
u32
index_block_size
;
/* Size of an index block. */
u8
index_block_size_bits
;
/* Log2 of the above. */
u32
index_vcn_size
;
/* Size of a vcn in this
directory index. */
u8
index_vcn_size_bits
;
/* Log2 of the above. */
s64
bmp_size
;
/* Size of the $I30 bitmap. */
s64
bmp_initialized_size
;
/* Copy from $I30 bitmap. */
s64
bmp_allocated_size
;
/* Copy from $I30 bitmap. */
run_list
bmp_rl
;
/* Run list for the $I30 bitmap
if it is non-resident. */
u8
index_block_size_bits
;
/* Log2 of the above. */
u8
index_vcn_size_bits
;
/* Log2 of the above. */
}
SN
(
idm
);
struct
{
/* It is a compressed file. */
struct
{
/* It is a compressed file or fake inode. */
s64
compressed_size
;
/* Copy from $DATA. */
u32
compression_block_size
;
/* Size of a compression
block (cb). */
u8
compression_block_size_bits
;
/* Log2 of the size of
...
...
@@ -92,13 +112,13 @@ struct _ntfs_inode {
u8
compression_block_clusters
;
/* Number of clusters
per compression
block. */
s64
compressed_size
;
/* Copy from $DATA. */
}
SN
(
icf
);
}
SN
(
idc
);
struct
semaphore
extent_lock
;
/* Lock for accessing/modifying the
below . */
s32
nr_extents
;
/* For a base mft record, the number of attached extent
inodes (0 if none), for extent records this is -1. */
inodes (0 if none), for extent records and for fake
inodes describing an attribute this is -1. */
union
{
/* This union is only used if nr_extents != 0. */
ntfs_inode
**
extent_ntfs_inos
;
/* For nr_extents > 0, array of
the ntfs inodes of the extent
...
...
@@ -107,7 +127,9 @@ struct _ntfs_inode {
been loaded. */
ntfs_inode
*
base_ntfs_ino
;
/* For nr_extents == -1, the
ntfs inode of the base mft
record. */
record. For fake inodes, the
real (base) inode to which
the attribute belongs. */
}
SN
(
ine
);
};
...
...
@@ -115,6 +137,79 @@ struct _ntfs_inode {
#define _ICF(X) SC(idc.icf,X)
#define _INE(X) SC(ine,X)
/*
* Defined bits for the state field in the ntfs_inode structure.
* (f) = files only, (d) = directories only, (a) = attributes/fake inodes only
*/
typedef
enum
{
NI_Dirty
,
/* 1: Mft record needs to be written to disk. */
NI_AttrList
,
/* 1: Mft record contains an attribute list. */
NI_AttrListNonResident
,
/* 1: Attribute list is non-resident. Implies
NI_AttrList is set. */
NI_Attr
,
/* 1: Fake inode for attribute i/o.
0: Real inode or extent inode. */
NI_MstProtected
,
/* 1: Attribute is protected by MST fixups.
0: Attribute is not protected by fixups. */
NI_NonResident
,
/* 1: Unnamed data attr is non-resident (f).
1: Attribute is non-resident (a). */
NI_IndexAllocPresent
=
NI_NonResident
,
/* 1: $I30 index alloc attr is
present (d). */
NI_Compressed
,
/* 1: Unnamed data attr is compressed (f).
1: Create compressed files by default (d).
1: Attribute is compressed (a). */
NI_Encrypted
,
/* 1: Unnamed data attr is encrypted (f).
1: Create encrypted files by default (d).
1: Attribute is encrypted (a). */
NI_Sparse
,
/* 1: Unnamed data attr is sparse (f).
1: Create sparse files by default (d).
1: Attribute is sparse (a). */
NI_BmpNonResident
,
/* 1: $I30 bitmap attr is non resident (d). */
}
ntfs_inode_state_bits
;
/*
* NOTE: We should be adding dirty mft records to a list somewhere and they
* should be independent of the (ntfs/vfs) inode structure so that an inode can
* be removed but the record can be left dirty for syncing later.
*/
/*
* Macro tricks to expand the NInoFoo(), NInoSetFoo(), and NInoClearFoo()
* functions.
*/
#define NINO_FNS(flag) \
static inline int NIno##flag(ntfs_inode *ni) \
{ \
return test_bit(NI_##flag, &(ni)->state); \
} \
static inline void NInoSet##flag(ntfs_inode *ni) \
{ \
set_bit(NI_##flag, &(ni)->state); \
} \
static inline void NInoClear##flag(ntfs_inode *ni) \
{ \
clear_bit(NI_##flag, &(ni)->state); \
}
/* Emit the ntfs inode bitops functions. */
NINO_FNS
(
Dirty
)
NINO_FNS
(
AttrList
)
NINO_FNS
(
AttrListNonResident
)
NINO_FNS
(
Attr
)
NINO_FNS
(
MstProtected
)
NINO_FNS
(
NonResident
)
NINO_FNS
(
IndexAllocPresent
)
NINO_FNS
(
Compressed
)
NINO_FNS
(
Encrypted
)
NINO_FNS
(
Sparse
)
NINO_FNS
(
BmpNonResident
)
/*
* The full structure containing a ntfs_inode and a vfs struct inode. Used for
* all real and fake inodes but not for extent inodes which lack the vfs struct
* inode.
*/
typedef
struct
{
ntfs_inode
ntfs_inode
;
struct
inode
vfs_inode
;
/* The vfs inode structure. */
...
...
@@ -136,14 +231,16 @@ static inline struct inode *VFS_I(ntfs_inode *ni)
return
&
((
big_ntfs_inode
*
)
ni
)
->
vfs_inode
;
}
extern
struct
inode
*
ntfs_iget
(
struct
super_block
*
sb
,
unsigned
long
mft_no
);
extern
struct
inode
*
ntfs_alloc_big_inode
(
struct
super_block
*
sb
);
extern
void
ntfs_destroy_big_inode
(
struct
inode
*
inode
);
extern
void
ntfs_clear_big_inode
(
struct
inode
*
vi
);
extern
ntfs_inode
*
ntfs_new_inode
(
struct
super_block
*
sb
);
extern
void
ntfs_clear_inode
(
ntfs_inode
*
ni
);
extern
ntfs_inode
*
ntfs_new_extent_inode
(
struct
super_block
*
sb
,
unsigned
long
mft_no
);
extern
void
ntfs_clear_extent_inode
(
ntfs_inode
*
ni
);
extern
void
ntfs_read_inode
(
struct
inode
*
vi
);
extern
void
ntfs_read_inode_mount
(
struct
inode
*
vi
);
extern
void
ntfs_dirty_inode
(
struct
inode
*
vi
);
...
...
fs/ntfs/mft.c
View file @
7403ed3e
...
...
@@ -102,7 +102,7 @@ extern int ntfs_mst_readpage(struct file *, struct page *);
* ntfs_mft_aops - address space operations for access to $MFT
*
* Address space operations for access to $MFT. This allows us to simply use
*
read_cache_page() in map_mft_record
().
*
ntfs_map_page() in map_mft_record_page
().
*/
struct
address_space_operations
ntfs_mft_aops
=
{
writepage:
NULL
,
/* Write dirty page to disk. */
...
...
@@ -334,9 +334,9 @@ void unmap_mft_record(const int rw, ntfs_inode *ni)
/*
* If pure ntfs_inode, i.e. no vfs inode attached, we leave it to
* ntfs_clear_
inode() in the extent inode case, and to the caller in
*
the non-extent, yet pure ntfs inode case, to do the actual tear
* down of all structures and freeing of all allocated memory.
* ntfs_clear_
extent_inode() in the extent inode case, and to the
*
caller in the non-extent, yet pure ntfs inode case, to do the actual
*
tear
down of all structures and freeing of all allocated memory.
*/
return
;
}
...
...
@@ -417,14 +417,13 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
return
m
;
}
/* Record wasn't there. Get a new ntfs inode and initialize it. */
ni
=
ntfs_new_
inode
(
base_ni
->
vol
->
sb
);
ni
=
ntfs_new_
extent_inode
(
base_ni
->
vol
->
sb
,
mft_no
);
if
(
!
ni
)
{
up
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
return
ERR_PTR
(
-
ENOMEM
);
}
ni
->
vol
=
base_ni
->
vol
;
ni
->
mft_no
=
mft_no
;
ni
->
seq_no
=
seq_no
;
ni
->
nr_extents
=
-
1
;
ni
->
_INE
(
base_ntfs_ino
)
=
base_ni
;
...
...
@@ -433,7 +432,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
if
(
IS_ERR
(
m
))
{
up
(
&
base_ni
->
extent_lock
);
atomic_dec
(
&
base_ni
->
count
);
ntfs_clear_inode
(
ni
);
ntfs_clear_
extent_
inode
(
ni
);
goto
map_err_out
;
}
/* Verify the sequence number. */
...
...
@@ -479,7 +478,7 @@ MFT_RECORD *map_extent_mft_record(ntfs_inode *base_ni, MFT_REF mref,
* release it or we will leak memory.
*/
if
(
destroy_ni
)
ntfs_clear_inode
(
ni
);
ntfs_clear_
extent_
inode
(
ni
);
return
m
;
}
fs/ntfs/namei.c
View file @
7403ed3e
...
...
@@ -38,8 +38,8 @@
* supplying the name of the inode in @dent->d_name.name. ntfs_lookup()
* converts the name to Unicode and walks the contents of the directory inode
* @dir_ino looking for the converted Unicode name. If the name is found in the
* directory, the corresponding inode is loaded by calling
iget() on its inode
* number and the inode is associated with the dentry @dent via a call to
* directory, the corresponding inode is loaded by calling
ntfs_iget() on its
*
inode
number and the inode is associated with the dentry @dent via a call to
* d_add().
*
* If the name is not found in the directory, a NULL inode is inserted into the
...
...
@@ -111,9 +111,9 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
kmem_cache_free
(
ntfs_name_cache
,
uname
);
if
(
!
IS_ERR_MREF
(
mref
))
{
dent_ino
=
MREF
(
mref
);
ntfs_debug
(
"Found inode 0x%lx. Calling iget."
,
dent_ino
);
dent_inode
=
iget
(
vol
->
sb
,
dent_ino
);
if
(
dent_inode
)
{
ntfs_debug
(
"Found inode 0x%lx. Calling
ntfs_
iget."
,
dent_ino
);
dent_inode
=
ntfs_
iget
(
vol
->
sb
,
dent_ino
);
if
(
likely
(
!
IS_ERR
(
dent_inode
))
)
{
/* Consistency check. */
if
(
MSEQNO
(
mref
)
==
NTFS_I
(
dent_inode
)
->
seq_no
||
dent_ino
==
FILE_MFT
)
{
...
...
@@ -132,16 +132,19 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
ntfs_error
(
vol
->
sb
,
"Found stale reference to inode "
"0x%lx (reference sequence number = "
"0x%x, inode sequence number = 0x%x, "
"returning -E
ACCES
. Run chkdsk."
,
"returning -E
IO
. Run chkdsk."
,
dent_ino
,
MSEQNO
(
mref
),
NTFS_I
(
dent_inode
)
->
seq_no
);
iput
(
dent_inode
);
dent_inode
=
ERR_PTR
(
-
EIO
);
}
else
ntfs_error
(
vol
->
sb
,
"iget(0x%lx) failed, returning "
"-EACCES."
,
dent_ino
);
ntfs_error
(
vol
->
sb
,
"ntfs_iget(0x%lx) failed with "
"error code %li."
,
dent_ino
,
PTR_ERR
(
dent_inode
));
if
(
name
)
kfree
(
name
);
return
ERR_PTR
(
-
EACCES
);
/* Return the error code. */
return
(
struct
dentry
*
)
dent_inode
;
}
/* It is guaranteed that name is no longer allocated at this point. */
if
(
MREF_ERR
(
mref
)
==
-
ENOENT
)
{
...
...
@@ -256,7 +259,8 @@ static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
BUG_ON
(
real_dent
->
d_inode
!=
dent_inode
);
/*
* Already have the inode and the dentry attached, decrement
* the reference count to balance the iget() we did earlier on.
* the reference count to balance the ntfs_iget() we did
* earlier on.
*/
iput
(
dent_inode
);
return
real_dent
;
...
...
fs/ntfs/ntfs.h
View file @
7403ed3e
...
...
@@ -53,41 +53,6 @@ typedef enum {
NTFS_MAX_NAME_LEN
=
255
,
}
NTFS_CONSTANTS
;
/*
* Defined bits for the state field in the ntfs_inode structure.
* (f) = files only, (d) = directories only
*/
typedef
enum
{
NI_Dirty
,
/* 1: Mft record needs to be written to disk. */
NI_AttrList
,
/* 1: Mft record contains an attribute list. */
NI_AttrListNonResident
,
/* 1: Attribute list is non-resident. Implies
NI_AttrList is set. */
NI_NonResident
,
/* 1: Unnamed data attr is non-resident (f).
1: $I30 index alloc attr is present (d). */
NI_Compressed
,
/* 1: Unnamed data attr is compressed (f).
1: Create compressed files by default (d). */
NI_Encrypted
,
/* 1: Unnamed data attr is encrypted (f).
1: Create encrypted files by default (d). */
NI_BmpNonResident
,
/* 1: $I30 bitmap attr is non resident (d). */
}
ntfs_inode_state_bits
;
/*
* NOTE: We should be adding dirty mft records to a list somewhere and they
* should be independent of the (ntfs/vfs) inode structure so that an inode can
* be removed but the record can be left dirty for syncing later.
*/
#define NInoDirty(n_ino) test_bit(NI_Dirty, &(n_ino)->state)
#define NInoSetDirty(n_ino) set_bit(NI_Dirty, &(n_ino)->state)
#define NInoClearDirty(n_ino) clear_bit(NI_Dirty, &(n_ino)->state)
#define NInoAttrList(n_ino) test_bit(NI_AttrList, &(n_ino)->state)
#define NInoNonResident(n_ino) test_bit(NI_NonResident, &(n_ino)->state)
#define NInoIndexAllocPresent(n_ino) test_bit(NI_NonResident, &(n_ino)->state)
#define NInoCompressed(n_ino) test_bit(NI_Compressed, &(n_ino)->state)
#define NInoEncrypted(n_ino) test_bit(NI_Encrypted, &(n_ino)->state)
#define NInoBmpNonResident(n_ino) test_bit(NI_BmpNonResident, &(n_ino)->state)
/* Global variables. */
/* Slab caches (from super.c). */
...
...
fs/ntfs/super.c
View file @
7403ed3e
...
...
@@ -605,17 +605,17 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
sizeof
(
unsigned
long
)
*
4
);
return
FALSE
;
}
vol
->
_VCL
(
nr_clusters
)
=
ll
;
ntfs_debug
(
"vol->nr_clusters = 0x%Lx"
,
(
long
long
)
vol
->
_VCL
(
nr_clusters
)
);
vol
->
nr_clusters
=
ll
;
ntfs_debug
(
"vol->nr_clusters = 0x%Lx"
,
(
long
long
)
vol
->
nr_clusters
);
ll
=
sle64_to_cpu
(
b
->
mft_lcn
);
if
(
ll
>=
vol
->
_VCL
(
nr_clusters
)
)
{
if
(
ll
>=
vol
->
nr_clusters
)
{
ntfs_error
(
vol
->
sb
,
"MFT LCN is beyond end of volume. Weird."
);
return
FALSE
;
}
vol
->
mft_lcn
=
ll
;
ntfs_debug
(
"vol->mft_lcn = 0x%Lx"
,
(
long
long
)
vol
->
mft_lcn
);
ll
=
sle64_to_cpu
(
b
->
mftmirr_lcn
);
if
(
ll
>=
vol
->
_VCL
(
nr_clusters
)
)
{
if
(
ll
>=
vol
->
nr_clusters
)
{
ntfs_error
(
vol
->
sb
,
"MFTMirr LCN is beyond end of volume. "
"Weird."
);
return
FALSE
;
...
...
@@ -629,7 +629,7 @@ static BOOL parse_ntfs_boot_sector(ntfs_volume *vol, const NTFS_BOOT_SECTOR *b)
* Determine MFT zone size. This is not strictly the right place to do
* this, but I am too lazy to create a function especially for it...
*/
vol
->
mft_zone_end
=
vol
->
_VCL
(
nr_clusters
)
;
vol
->
mft_zone_end
=
vol
->
nr_clusters
;
switch
(
vol
->
mft_zone_multiplier
)
{
/* % of volume size in clusters */
case
4
:
vol
->
mft_zone_end
=
vol
->
mft_zone_end
>>
1
;
/* 50% */
...
...
@@ -678,9 +678,9 @@ static BOOL load_and_init_upcase(ntfs_volume *vol)
ntfs_debug
(
"Entering."
);
/* Read upcase table and setup vol->upcase and vol->upcase_len. */
ino
=
iget
(
sb
,
FILE_UpCase
);
if
(
!
ino
||
is_bad_inode
(
ino
))
{
if
(
ino
)
ino
=
ntfs_
iget
(
sb
,
FILE_UpCase
);
if
(
IS_ERR
(
ino
)
||
is_bad_inode
(
ino
))
{
if
(
!
IS_ERR
(
ino
)
)
iput
(
ino
);
goto
upcase_failed
;
}
...
...
@@ -848,7 +848,7 @@ static BOOL load_system_files(ntfs_volume *vol)
vol
->
mftbmp_allocated_size
=
sle64_to_cpu
(
attr
->
_ANR
(
allocated_size
));
/* Consistency check. */
if
(
vol
->
mftbmp_size
<
(
vol
->
_VMM
(
nr_mft_records
)
+
7
)
>>
3
)
{
if
(
vol
->
mftbmp_size
<
(
vol
->
nr_mft_records
+
7
)
>>
3
)
{
ntfs_error
(
sb
,
"$MFT/$BITMAP is too short to "
"contain a complete mft "
"bitmap: impossible. $MFT is "
...
...
@@ -914,9 +914,9 @@ static BOOL load_system_files(ntfs_volume *vol)
// volume read-write...
/* Get mft mirror inode. */
vol
->
mftmirr_ino
=
iget
(
sb
,
FILE_MFTMirr
);
if
(
!
vol
->
mftmirr_ino
||
is_bad_inode
(
vol
->
mftmirr_ino
))
{
if
(
is_bad_inode
(
vol
->
mftmirr_ino
))
vol
->
mftmirr_ino
=
ntfs_
iget
(
sb
,
FILE_MFTMirr
);
if
(
IS_ERR
(
vol
->
mftmirr_ino
)
||
is_bad_inode
(
vol
->
mftmirr_ino
))
{
if
(
!
IS_ERR
(
vol
->
mftmirr_ino
))
iput
(
vol
->
mftmirr_ino
);
ntfs_error
(
sb
,
"Failed to load $MFTMirr."
);
return
FALSE
;
...
...
@@ -932,13 +932,13 @@ static BOOL load_system_files(ntfs_volume *vol)
* need for any locking at this stage as we are already running
* exclusively as we are mount in progress task.
*/
vol
->
lcnbmp_ino
=
iget
(
sb
,
FILE_Bitmap
);
if
(
!
vol
->
lcnbmp_ino
||
is_bad_inode
(
vol
->
lcnbmp_ino
))
{
if
(
is_bad_inode
(
vol
->
lcnbmp_ino
))
vol
->
lcnbmp_ino
=
ntfs_
iget
(
sb
,
FILE_Bitmap
);
if
(
IS_ERR
(
vol
->
lcnbmp_ino
)
||
is_bad_inode
(
vol
->
lcnbmp_ino
))
{
if
(
!
IS_ERR
(
vol
->
lcnbmp_ino
))
iput
(
vol
->
lcnbmp_ino
);
goto
bitmap_failed
;
}
if
((
vol
->
_VCL
(
nr_lcn_bits
)
+
7
)
>>
3
>
vol
->
lcnbmp_ino
->
i_size
)
{
if
((
vol
->
nr_clusters
+
7
)
>>
3
>
vol
->
lcnbmp_ino
->
i_size
)
{
iput
(
vol
->
lcnbmp_ino
);
bitmap_failed:
ntfs_error
(
sb
,
"Failed to load $Bitmap."
);
...
...
@@ -948,9 +948,9 @@ static BOOL load_system_files(ntfs_volume *vol)
* Get the volume inode and setup our cache of the volume flags and
* version.
*/
vol
->
vol_ino
=
iget
(
sb
,
FILE_Volume
);
if
(
!
vol
->
vol_ino
||
is_bad_inode
(
vol
->
vol_ino
))
{
if
(
is_bad_inode
(
vol
->
vol_ino
))
vol
->
vol_ino
=
ntfs_
iget
(
sb
,
FILE_Volume
);
if
(
IS_ERR
(
vol
->
vol_ino
)
||
is_bad_inode
(
vol
->
vol_ino
))
{
if
(
!
IS_ERR
(
vol
->
vol_ino
))
iput
(
vol
->
vol_ino
);
volume_failed:
ntfs_error
(
sb
,
"Failed to load $Volume."
);
...
...
@@ -993,9 +993,9 @@ static BOOL load_system_files(ntfs_volume *vol)
* Get the inode for the logfile and empty it if this is a read-write
* mount.
*/
tmp_ino
=
iget
(
sb
,
FILE_LogFile
);
if
(
!
tmp_ino
||
is_bad_inode
(
tmp_ino
))
{
if
(
is_bad_inode
(
tmp_ino
))
tmp_ino
=
ntfs_
iget
(
sb
,
FILE_LogFile
);
if
(
IS_ERR
(
tmp_ino
)
||
is_bad_inode
(
tmp_ino
))
{
if
(
!
IS_ERR
(
tmp_ino
))
iput
(
tmp_ino
);
ntfs_error
(
sb
,
"Failed to load $LogFile."
);
// FIMXE: We only want to empty the thing so pointless bailing
...
...
@@ -1010,9 +1010,9 @@ static BOOL load_system_files(ntfs_volume *vol)
* Get the inode for the attribute definitions file and parse the
* attribute definitions.
*/
tmp_ino
=
iget
(
sb
,
FILE_AttrDef
);
if
(
!
tmp_ino
||
is_bad_inode
(
tmp_ino
))
{
if
(
is_bad_inode
(
tmp_ino
))
tmp_ino
=
ntfs_
iget
(
sb
,
FILE_AttrDef
);
if
(
IS_ERR
(
tmp_ino
)
||
is_bad_inode
(
tmp_ino
))
{
if
(
!
IS_ERR
(
tmp_ino
))
iput
(
tmp_ino
);
ntfs_error
(
sb
,
"Failed to load $AttrDef."
);
goto
iput_vol_bmp_mirr_err_out
;
...
...
@@ -1020,9 +1020,9 @@ static BOOL load_system_files(ntfs_volume *vol)
// FIXME: Parse the attribute definitions.
iput
(
tmp_ino
);
/* Get the root directory inode. */
vol
->
root_ino
=
iget
(
sb
,
FILE_root
);
if
(
!
vol
->
root_ino
||
is_bad_inode
(
vol
->
root_ino
))
{
if
(
is_bad_inode
(
vol
->
root_ino
))
vol
->
root_ino
=
ntfs_
iget
(
sb
,
FILE_root
);
if
(
IS_ERR
(
vol
->
root_ino
)
||
is_bad_inode
(
vol
->
root_ino
))
{
if
(
!
IS_ERR
(
vol
->
root_ino
))
iput
(
vol
->
root_ino
);
ntfs_error
(
sb
,
"Failed to load root directory."
);
goto
iput_vol_bmp_mirr_err_out
;
...
...
@@ -1032,18 +1032,18 @@ static BOOL load_system_files(ntfs_volume *vol)
return
TRUE
;
/* NTFS 3.0+ specific initialization. */
/* Get the security descriptors inode. */
vol
->
secure_ino
=
iget
(
sb
,
FILE_Secure
);
if
(
!
vol
->
secure_ino
||
is_bad_inode
(
vol
->
secure_ino
))
{
if
(
is_bad_inode
(
vol
->
secure_ino
))
vol
->
secure_ino
=
ntfs_
iget
(
sb
,
FILE_Secure
);
if
(
IS_ERR
(
vol
->
secure_ino
)
||
is_bad_inode
(
vol
->
secure_ino
))
{
if
(
!
IS_ERR
(
vol
->
secure_ino
))
iput
(
vol
->
secure_ino
);
ntfs_error
(
sb
,
"Failed to load $Secure."
);
goto
iput_root_vol_bmp_mirr_err_out
;
}
// FIXME: Initialize security.
/* Get the extended system files' directory inode. */
tmp_ino
=
iget
(
sb
,
FILE_Extend
);
if
(
!
tmp_ino
||
is_bad_inode
(
tmp_ino
))
{
if
(
is_bad_inode
(
tmp_ino
))
tmp_ino
=
ntfs_
iget
(
sb
,
FILE_Extend
);
if
(
IS_ERR
(
tmp_ino
)
||
is_bad_inode
(
tmp_ino
))
{
if
(
!
IS_ERR
(
tmp_ino
))
iput
(
tmp_ino
);
ntfs_error
(
sb
,
"Failed to load $Extend."
);
goto
iput_sec_root_vol_bmp_mirr_err_out
;
...
...
@@ -1051,8 +1051,8 @@ static BOOL load_system_files(ntfs_volume *vol)
// FIXME: Do something. E.g. want to delete the $UsnJrnl if exists.
// Note we might be doing this at the wrong level; we might want to
// d_alloc_root() and then do a "normal" open(2) of $Extend\$UsnJrnl
// rather than using
iget here, as we don't know the inode number fo
r
// the files in $Extend directory.
// rather than using
ntfs_iget here, as we don't know the inode numbe
r
//
for
the files in $Extend directory.
iput
(
tmp_ino
);
return
TRUE
;
iput_sec_root_vol_bmp_mirr_err_out:
...
...
@@ -1172,7 +1172,7 @@ s64 get_nr_free_clusters(ntfs_volume *vol)
* Convert the number of bits into bytes rounded up, then convert into
* multiples of PAGE_CACHE_SIZE.
*/
max_index
=
(
vol
->
_VCL
(
nr_clusters
)
+
7
)
>>
(
3
+
PAGE_CACHE_SHIFT
);
max_index
=
(
vol
->
nr_clusters
+
7
)
>>
(
3
+
PAGE_CACHE_SHIFT
);
/* Use multiples of 4 bytes. */
max_size
=
PAGE_CACHE_SIZE
>>
2
;
ntfs_debug
(
"Reading $BITMAP, max_index = 0x%lx, max_size = 0x%x."
,
...
...
@@ -1211,7 +1211,7 @@ s64 get_nr_free_clusters(ntfs_volume *vol)
* Get the multiples of 4 bytes in use in the final partial
* page.
*/
max_size
=
((((
vol
->
_VCL
(
nr_clusters
)
+
7
)
>>
3
)
&
~
PAGE_CACHE_MASK
)
max_size
=
((((
vol
->
nr_clusters
+
7
)
>>
3
)
&
~
PAGE_CACHE_MASK
)
+
3
)
>>
2
;
/* If there is a partial page go back and do it. */
if
(
max_size
)
{
...
...
@@ -1254,7 +1254,7 @@ unsigned long get_nr_free_mft_records(ntfs_volume *vol)
* Convert the number of bits into bytes rounded up, then convert into
* multiples of PAGE_CACHE_SIZE.
*/
max_index
=
(
vol
->
_VMM
(
nr_mft_records
)
+
7
)
>>
(
3
+
PAGE_CACHE_SHIFT
);
max_index
=
(
vol
->
nr_mft_records
+
7
)
>>
(
3
+
PAGE_CACHE_SHIFT
);
/* Use multiples of 4 bytes. */
max_size
=
PAGE_CACHE_SIZE
>>
2
;
ntfs_debug
(
"Reading $MFT/$BITMAP, max_index = 0x%lx, max_size = "
...
...
@@ -1293,12 +1293,12 @@ unsigned long get_nr_free_mft_records(ntfs_volume *vol)
* Get the multiples of 4 bytes in use in the final partial
* page.
*/
max_size
=
((((
vol
->
_VMM
(
nr_mft_records
)
+
7
)
>>
3
)
&
max_size
=
((((
vol
->
nr_mft_records
+
7
)
>>
3
)
&
~
PAGE_CACHE_MASK
)
+
3
)
>>
2
;
/* If there is a partial page go back and do it. */
if
(
max_size
)
{
/* Compensate for out of bounds zero bits. */
if
((
i
=
vol
->
_VMM
(
nr_mft_records
)
&
31
))
if
((
i
=
vol
->
nr_mft_records
&
31
))
nr_free
-=
32
-
i
;
ntfs_debug
(
"Handling partial page, max_size = 0x%x"
,
max_size
);
...
...
@@ -1345,7 +1345,7 @@ int ntfs_statfs(struct super_block *sb, struct statfs *sfs)
* inodes are also stored in data blocs ($MFT is a file) this is just
* the total clusters.
*/
sfs
->
f_blocks
=
vol
->
_VCL
(
nr_clusters
)
<<
vol
->
cluster_size_bits
>>
sfs
->
f_blocks
=
vol
->
nr_clusters
<<
vol
->
cluster_size_bits
>>
PAGE_CACHE_SHIFT
;
/* Free data blocks in file system in units of f_bsize. */
size
=
get_nr_free_clusters
(
vol
)
<<
vol
->
cluster_size_bits
>>
...
...
@@ -1394,8 +1394,6 @@ struct super_operations ntfs_mount_sops = {
struct
super_operations
ntfs_sops
=
{
alloc_inode:
ntfs_alloc_big_inode
,
/* VFS: Allocate a new inode. */
destroy_inode:
ntfs_destroy_big_inode
,
/* VFS: Deallocate an inode. */
read_inode:
ntfs_read_inode
,
/* VFS: Load inode from disk,
called from iget(). */
dirty_inode:
ntfs_dirty_inode
,
/* VFS: Called from
__mark_inode_dirty(). */
//write_inode: NULL, /* VFS: Write dirty inode to disk. */
...
...
@@ -1575,9 +1573,9 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
/*
* Now load the metadata required for the page cache and our address
* space operations to function. We do this by setting up a specialised
* read_inode method and then just calling
iget() to obtain the inode
*
for $MFT which is sufficient to allow our normal inode operations
* and associated address space operations to function.
* read_inode method and then just calling
the normal iget() to obtain
*
the inode for $MFT which is sufficient to allow our normal inode
*
operations
and associated address space operations to function.
*/
/*
* Poison vol->mft_ino so we know whether iget() called into our
...
...
@@ -1601,9 +1599,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
* Note: sb->s_op has already been set to &ntfs_sops by our specialized
* ntfs_read_inode_mount() method when it was invoked by iget().
*/
down
(
&
ntfs_lock
);
/*
* The current mount is a compression user if the cluster size is
* less than or equal 4kiB.
...
...
@@ -1618,7 +1614,6 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
goto
iput_tmp_ino_err_out_now
;
}
}
/*
* Increment the number of mounts and generate the global default
* upcase table if necessary. Also temporarily increment the number of
...
...
@@ -1629,12 +1624,10 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
ntfs_nr_upcase_users
++
;
up
(
&
ntfs_lock
);
/*
* From now on, ignore @silent parameter. If we fail below this line,
* it will be due to a corrupt fs or a system error, so we report it.
*/
/*
* Open the system files with normal access functions and complete
* setting up the ntfs super block.
...
...
@@ -1643,9 +1636,8 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
ntfs_error
(
sb
,
"Failed to load system files."
);
goto
unl_upcase_iput_tmp_ino_err_out_now
;
}
if
((
sb
->
s_root
=
d_alloc_root
(
vol
->
root_ino
)))
{
/* We increment i_count simulating an iget(). */
/* We increment i_count simulating an
ntfs_
iget(). */
atomic_inc
(
&
vol
->
root_ino
->
i_count
);
ntfs_debug
(
"Exiting, status successful."
);
/* Release the default upcase if it has no users. */
...
...
@@ -1709,10 +1701,11 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
}
#undef OGIN
/*
* This is needed to get ntfs_clear_inode() called for each inode we
* have ever called iget()/iput() on, otherwise we A) leak resources
* and B) a subsequent mount fails automatically due to iget() never
* calling down into our ntfs_read_inode{_mount}() methods again...
* This is needed to get ntfs_clear_extent_inode() called for each
* inode we have ever called ntfs_iget()/iput() on, otherwise we A)
* leak resources and B) a subsequent mount fails automatically due to
* ntfs_iget() never calling down into our ntfs_read_locked_inode()
* method again...
*/
if
(
invalidate_inodes
(
sb
))
{
ntfs_error
(
sb
,
"Busy inodes left. This is most likely a NTFS "
...
...
fs/ntfs/volume.h
View file @
7403ed3e
...
...
@@ -3,7 +3,7 @@
* of the Linux-NTFS project.
*
* Copyright (c) 2001,2002 Anton Altaparmakov.
* Copyright (
C
) 2002 Richard Russon.
* Copyright (
c
) 2002 Richard Russon.
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
...
...
@@ -89,10 +89,8 @@ typedef struct {
u32
index_record_size
;
/* in bytes */
u32
index_record_size_mask
;
/* index_record_size - 1 */
u8
index_record_size_bits
;
/* log2(index_record_size) */
union
{
LCN
nr_clusters
;
/* Volume size in clusters. */
LCN
nr_lcn_bits
;
/* Number of bits in lcn bitmap. */
}
SN
(
vcl
);
LCN
nr_clusters
;
/* Volume size in clusters == number of
bits in lcn bitmap. */
LCN
mft_lcn
;
/* Cluster location of mft data. */
LCN
mftmirr_lcn
;
/* Cluster location of copy of mft. */
u64
serial_no
;
/* The volume serial number. */
...
...
@@ -104,10 +102,8 @@ typedef struct {
struct
inode
*
mft_ino
;
/* The VFS inode of $MFT. */
struct
rw_semaphore
mftbmp_lock
;
/* Lock for serializing accesses to the
mft record bitmap ($MFT/$BITMAP). */
union
{
unsigned
long
nr_mft_records
;
/* Number of mft records. */
unsigned
long
nr_mft_bits
;
/* Number of bits in mft bitmap. */
}
SN
(
vmm
);
unsigned
long
nr_mft_records
;
/* Number of mft records == number of
bits in mft bitmap. */
struct
address_space
mftbmp_mapping
;
/* Page cache for $MFT/$BITMAP. */
run_list
mftbmp_rl
;
/* Run list for $MFT/$BITMAP. */
s64
mftbmp_size
;
/* Data size of $MFT/$BITMAP. */
...
...
@@ -128,8 +124,5 @@ typedef struct {
struct
nls_table
*
nls_map
;
}
ntfs_volume
;
#define _VCL(X) SC(vcl,X)
#define _VMM(X) SC(vmm,X)
#endif
/* _LINUX_NTFS_VOLUME_H */
fs/proc/array.c
View file @
7403ed3e
...
...
@@ -71,6 +71,7 @@
#include <linux/signal.h>
#include <linux/highmem.h>
#include <linux/file.h>
#include <linux/times.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
...
...
@@ -360,10 +361,10 @@ int proc_pid_stat(struct task_struct *task, char * buffer)
task
->
cmin_flt
,
task
->
maj_flt
,
task
->
cmaj_flt
,
task
->
times
.
tms_utime
,
task
->
times
.
tms_stime
,
task
->
times
.
tms_cutime
,
task
->
times
.
tms_cstime
,
jiffies_to_clock_t
(
task
->
utime
)
,
jiffies_to_clock_t
(
task
->
stime
)
,
jiffies_to_clock_t
(
task
->
cutime
)
,
jiffies_to_clock_t
(
task
->
cstime
)
,
priority
,
nice
,
0UL
/* removed */
,
...
...
@@ -692,8 +693,8 @@ int proc_pid_cpu(struct task_struct *task, char * buffer)
len
=
sprintf
(
buffer
,
"cpu %lu %lu
\n
"
,
task
->
times
.
tms_
utime
,
task
->
times
.
tms_
stime
);
task
->
utime
,
task
->
stime
);
for
(
i
=
0
;
i
<
NR_CPUS
;
i
++
)
{
if
(
cpu_online
(
i
))
...
...
fs/proc/proc_misc.c
View file @
7403ed3e
...
...
@@ -98,7 +98,7 @@ static int uptime_read_proc(char *page, char **start, off_t off,
int
len
;
uptime
=
jiffies
;
idle
=
init_task
.
times
.
tms_utime
+
init_task
.
times
.
tms_
stime
;
idle
=
init_task
.
utime
+
init_task
.
stime
;
/* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
that would overflow about every five days at HZ == 100.
...
...
include/asm-i386/param.h
View file @
7403ed3e
#ifndef _ASMi386_PARAM_H
#define _ASMi386_PARAM_H
#ifdef __KERNEL__
# define HZ 1000
/* Internal kernel timer frequency */
# define USER_HZ 100
/* .. some user interfaces are in "ticks" */
# define CLOCKS_PER_SEC (USER_HZ)
/* like times() */
#endif
#ifndef HZ
#define HZ 100
#endif
...
...
@@ -17,8 +23,4 @@
#define MAXHOSTNAMELEN 64
/* max length of hostname */
#ifdef __KERNEL__
# define CLOCKS_PER_SEC 100
/* frequency at which times() counts */
#endif
#endif
include/linux/sched.h
View file @
7403ed3e
...
...
@@ -10,7 +10,6 @@ extern unsigned long event;
#include <linux/threads.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/times.h>
#include <linux/timex.h>
#include <linux/jiffies.h>
#include <linux/rbtree.h>
...
...
@@ -310,7 +309,7 @@ struct task_struct {
unsigned
long
it_real_value
,
it_prof_value
,
it_virt_value
;
unsigned
long
it_real_incr
,
it_prof_incr
,
it_virt_incr
;
struct
timer_list
real_timer
;
struct
tms
times
;
unsigned
long
utime
,
stime
,
cutime
,
cstime
;
unsigned
long
start_time
;
long
per_cpu_utime
[
NR_CPUS
],
per_cpu_stime
[
NR_CPUS
];
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
...
...
include/linux/time.h
View file @
7403ed3e
...
...
@@ -12,6 +12,16 @@ struct timespec {
};
#endif
/* _STRUCT_TIMESPEC */
struct
timeval
{
time_t
tv_sec
;
/* seconds */
suseconds_t
tv_usec
;
/* microseconds */
};
struct
timezone
{
int
tz_minuteswest
;
/* minutes west of Greenwich */
int
tz_dsttime
;
/* type of dst correction */
};
#ifdef __KERNEL__
/*
...
...
@@ -48,6 +58,27 @@ jiffies_to_timespec(unsigned long jiffies, struct timespec *value)
value
->
tv_sec
=
jiffies
/
HZ
;
}
/* Same for "timeval" */
static
__inline__
unsigned
long
timeval_to_jiffies
(
struct
timeval
*
value
)
{
unsigned
long
sec
=
value
->
tv_sec
;
long
usec
=
value
->
tv_usec
;
if
(
sec
>=
(
MAX_JIFFY_OFFSET
/
HZ
))
return
MAX_JIFFY_OFFSET
;
usec
+=
1000000L
/
HZ
-
1
;
usec
/=
1000000L
/
HZ
;
return
HZ
*
sec
+
usec
;
}
static
__inline__
void
jiffies_to_timeval
(
unsigned
long
jiffies
,
struct
timeval
*
value
)
{
value
->
tv_usec
=
(
jiffies
%
HZ
)
*
(
1000000L
/
HZ
);
value
->
tv_sec
=
jiffies
/
HZ
;
}
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
...
...
@@ -88,17 +119,6 @@ extern struct timeval xtime;
#endif
/* __KERNEL__ */
struct
timeval
{
time_t
tv_sec
;
/* seconds */
suseconds_t
tv_usec
;
/* microseconds */
};
struct
timezone
{
int
tz_minuteswest
;
/* minutes west of Greenwich */
int
tz_dsttime
;
/* type of dst correction */
};
#define NFDBITS __NFDBITS
#ifdef __KERNEL__
...
...
include/linux/times.h
View file @
7403ed3e
#ifndef _LINUX_TIMES_H
#define _LINUX_TIMES_H
#ifdef __KERNEL__
# define jiffies_to_clock_t(x) ((x) / (HZ / USER_HZ))
#endif
struct
tms
{
clock_t
tms_utime
;
clock_t
tms_stime
;
...
...
kernel/acct.c
View file @
7403ed3e
...
...
@@ -319,8 +319,8 @@ static void do_acct_process(long exitcode, struct file *file)
ac
.
ac_btime
=
CT_TO_SECS
(
current
->
start_time
)
+
(
xtime
.
tv_sec
-
(
jiffies
/
HZ
));
ac
.
ac_etime
=
encode_comp_t
(
jiffies
-
current
->
start_time
);
ac
.
ac_utime
=
encode_comp_t
(
current
->
times
.
tms_
utime
);
ac
.
ac_stime
=
encode_comp_t
(
current
->
times
.
tms_
stime
);
ac
.
ac_utime
=
encode_comp_t
(
current
->
utime
);
ac
.
ac_stime
=
encode_comp_t
(
current
->
stime
);
ac
.
ac_uid
=
current
->
uid
;
ac
.
ac_gid
=
current
->
gid
;
ac
.
ac_tty
=
(
current
->
tty
)
?
kdev_t_to_nr
(
current
->
tty
->
device
)
:
0
;
...
...
kernel/exit.c
View file @
7403ed3e
...
...
@@ -648,8 +648,8 @@ asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struc
}
goto
end_wait4
;
case
TASK_ZOMBIE
:
current
->
times
.
tms_cutime
+=
p
->
times
.
tms_utime
+
p
->
times
.
tms_
cutime
;
current
->
times
.
tms_cstime
+=
p
->
times
.
tms_stime
+
p
->
times
.
tms_
cstime
;
current
->
cutime
+=
p
->
utime
+
p
->
cutime
;
current
->
cstime
+=
p
->
stime
+
p
->
cstime
;
read_unlock
(
&
tasklist_lock
);
retval
=
ru
?
getrusage
(
p
,
RUSAGE_BOTH
,
ru
)
:
0
;
if
(
!
retval
&&
stat_addr
)
...
...
kernel/fork.c
View file @
7403ed3e
...
...
@@ -686,8 +686,8 @@ struct task_struct *do_fork(unsigned long clone_flags,
p
->
leader
=
0
;
/* session leadership doesn't inherit */
p
->
tty_old_pgrp
=
0
;
p
->
times
.
tms_utime
=
p
->
times
.
tms_
stime
=
0
;
p
->
times
.
tms_cutime
=
p
->
times
.
tms_
cstime
=
0
;
p
->
utime
=
p
->
stime
=
0
;
p
->
cutime
=
p
->
cstime
=
0
;
#ifdef CONFIG_SMP
{
int
i
;
...
...
kernel/itimer.c
View file @
7403ed3e
...
...
@@ -12,34 +12,6 @@
#include <asm/uaccess.h>
/*
* change timeval to jiffies, trying to avoid the
* most obvious overflows..
*
* The tv_*sec values are signed, but nothing seems to
* indicate whether we really should use them as signed values
* when doing itimers. POSIX doesn't mention this (but if
* alarm() uses itimers without checking, we have to use unsigned
* arithmetic).
*/
static
unsigned
long
tvtojiffies
(
struct
timeval
*
value
)
{
unsigned
long
sec
=
(
unsigned
)
value
->
tv_sec
;
unsigned
long
usec
=
(
unsigned
)
value
->
tv_usec
;
if
(
sec
>
(
ULONG_MAX
/
HZ
))
return
ULONG_MAX
;
usec
+=
1000000
/
HZ
-
1
;
usec
/=
1000000
/
HZ
;
return
HZ
*
sec
+
usec
;
}
static
void
jiffiestotv
(
unsigned
long
jiffies
,
struct
timeval
*
value
)
{
value
->
tv_usec
=
(
jiffies
%
HZ
)
*
(
1000000
/
HZ
);
value
->
tv_sec
=
jiffies
/
HZ
;
}
int
do_getitimer
(
int
which
,
struct
itimerval
*
value
)
{
register
unsigned
long
val
,
interval
;
...
...
@@ -70,8 +42,8 @@ int do_getitimer(int which, struct itimerval *value)
default:
return
(
-
EINVAL
);
}
jiffies
totv
(
val
,
&
value
->
it_value
);
jiffies
totv
(
interval
,
&
value
->
it_interval
);
jiffies
_to_timeval
(
val
,
&
value
->
it_value
);
jiffies
_to_timeval
(
interval
,
&
value
->
it_interval
);
return
0
;
}
...
...
@@ -110,8 +82,8 @@ int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
register
unsigned
long
i
,
j
;
int
k
;
i
=
t
vto
jiffies
(
&
value
->
it_interval
);
j
=
t
vto
jiffies
(
&
value
->
it_value
);
i
=
t
imeval_to_
jiffies
(
&
value
->
it_interval
);
j
=
t
imeval_to_
jiffies
(
&
value
->
it_value
);
if
(
ovalue
&&
(
k
=
do_getitimer
(
which
,
ovalue
))
<
0
)
return
k
;
switch
(
which
)
{
...
...
kernel/signal.c
View file @
7403ed3e
...
...
@@ -779,8 +779,8 @@ void do_notify_parent(struct task_struct *tsk, int sig)
info
.
si_uid
=
tsk
->
uid
;
/* FIXME: find out whether or not this is supposed to be c*time. */
info
.
si_utime
=
tsk
->
times
.
tms_
utime
;
info
.
si_stime
=
tsk
->
times
.
tms_
stime
;
info
.
si_utime
=
tsk
->
utime
;
info
.
si_stime
=
tsk
->
stime
;
status
=
tsk
->
exit_code
&
0x7f
;
why
=
SI_KERNEL
;
/* shouldn't happen */
...
...
kernel/sys.c
View file @
7403ed3e
...
...
@@ -18,6 +18,7 @@
#include <linux/fs.h>
#include <linux/tqueue.h>
#include <linux/device.h>
#include <linux/times.h>
#include <asm/uaccess.h>
#include <asm/io.h>
...
...
@@ -833,10 +834,16 @@ asmlinkage long sys_times(struct tms * tbuf)
* atomically safe type this is just fine. Conceptually its
* as if the syscall took an instant longer to occur.
*/
if
(
tbuf
)
if
(
copy_to_user
(
tbuf
,
&
current
->
times
,
sizeof
(
struct
tms
)))
if
(
tbuf
)
{
struct
tms
tmp
;
tmp
.
tms_utime
=
jiffies_to_clock_t
(
current
->
utime
);
tmp
.
tms_stime
=
jiffies_to_clock_t
(
current
->
stime
);
tmp
.
tms_cutime
=
jiffies_to_clock_t
(
current
->
cutime
);
tmp
.
tms_cstime
=
jiffies_to_clock_t
(
current
->
cstime
);
if
(
copy_to_user
(
tbuf
,
&
tmp
,
sizeof
(
struct
tms
)))
return
-
EFAULT
;
return
jiffies
;
}
return
jiffies_to_clock_t
(
jiffies
);
}
/*
...
...
@@ -1193,28 +1200,22 @@ int getrusage(struct task_struct *p, int who, struct rusage *ru)
memset
((
char
*
)
&
r
,
0
,
sizeof
(
r
));
switch
(
who
)
{
case
RUSAGE_SELF
:
r
.
ru_utime
.
tv_sec
=
CT_TO_SECS
(
p
->
times
.
tms_utime
);
r
.
ru_utime
.
tv_usec
=
CT_TO_USECS
(
p
->
times
.
tms_utime
);
r
.
ru_stime
.
tv_sec
=
CT_TO_SECS
(
p
->
times
.
tms_stime
);
r
.
ru_stime
.
tv_usec
=
CT_TO_USECS
(
p
->
times
.
tms_stime
);
jiffies_to_timeval
(
p
->
utime
,
&
r
.
ru_utime
);
jiffies_to_timeval
(
p
->
stime
,
&
r
.
ru_stime
);
r
.
ru_minflt
=
p
->
min_flt
;
r
.
ru_majflt
=
p
->
maj_flt
;
r
.
ru_nswap
=
p
->
nswap
;
break
;
case
RUSAGE_CHILDREN
:
r
.
ru_utime
.
tv_sec
=
CT_TO_SECS
(
p
->
times
.
tms_cutime
);
r
.
ru_utime
.
tv_usec
=
CT_TO_USECS
(
p
->
times
.
tms_cutime
);
r
.
ru_stime
.
tv_sec
=
CT_TO_SECS
(
p
->
times
.
tms_cstime
);
r
.
ru_stime
.
tv_usec
=
CT_TO_USECS
(
p
->
times
.
tms_cstime
);
jiffies_to_timeval
(
p
->
cutime
,
&
r
.
ru_utime
);
jiffies_to_timeval
(
p
->
cstime
,
&
r
.
ru_stime
);
r
.
ru_minflt
=
p
->
cmin_flt
;
r
.
ru_majflt
=
p
->
cmaj_flt
;
r
.
ru_nswap
=
p
->
cnswap
;
break
;
default:
r
.
ru_utime
.
tv_sec
=
CT_TO_SECS
(
p
->
times
.
tms_utime
+
p
->
times
.
tms_cutime
);
r
.
ru_utime
.
tv_usec
=
CT_TO_USECS
(
p
->
times
.
tms_utime
+
p
->
times
.
tms_cutime
);
r
.
ru_stime
.
tv_sec
=
CT_TO_SECS
(
p
->
times
.
tms_stime
+
p
->
times
.
tms_cstime
);
r
.
ru_stime
.
tv_usec
=
CT_TO_USECS
(
p
->
times
.
tms_stime
+
p
->
times
.
tms_cstime
);
jiffies_to_timeval
(
p
->
utime
+
p
->
cutime
,
&
r
.
ru_utime
);
jiffies_to_timeval
(
p
->
stime
+
p
->
cstime
,
&
r
.
ru_stime
);
r
.
ru_minflt
=
p
->
min_flt
+
p
->
cmin_flt
;
r
.
ru_majflt
=
p
->
maj_flt
+
p
->
cmaj_flt
;
r
.
ru_nswap
=
p
->
nswap
+
p
->
cnswap
;
...
...
kernel/timer.c
View file @
7403ed3e
...
...
@@ -527,8 +527,8 @@ static inline void do_process_times(struct task_struct *p,
{
unsigned
long
psecs
;
psecs
=
(
p
->
times
.
tms_
utime
+=
user
);
psecs
+=
(
p
->
times
.
tms_
stime
+=
system
);
psecs
=
(
p
->
utime
+=
user
);
psecs
+=
(
p
->
stime
+=
system
);
if
(
psecs
/
HZ
>
p
->
rlim
[
RLIMIT_CPU
].
rlim_cur
)
{
/* Send SIGXCPU every second.. */
if
(
!
(
psecs
%
HZ
))
...
...
mm/oom_kill.c
View file @
7403ed3e
...
...
@@ -72,7 +72,7 @@ static int badness(struct task_struct *p)
* very well in practice. This is not safe against jiffie wraps
* but we don't care _that_ much...
*/
cpu_time
=
(
p
->
times
.
tms_utime
+
p
->
times
.
tms_
stime
)
>>
(
SHIFT_HZ
+
3
);
cpu_time
=
(
p
->
utime
+
p
->
stime
)
>>
(
SHIFT_HZ
+
3
);
run_time
=
(
jiffies
-
p
->
start_time
)
>>
(
SHIFT_HZ
+
10
);
points
/=
int_sqrt
(
cpu_time
);
...
...
sound/oss/maestro.c
View file @
7403ed3e
...
...
@@ -3573,9 +3573,18 @@ maestro_probe(struct pci_dev *pcidev,const struct pci_device_id *pdid)
static
void
maestro_remove
(
struct
pci_dev
*
pcidev
)
{
struct
ess_card
*
card
=
pci_get_drvdata
(
pcidev
);
int
i
;
u32
n
;
/* XXX maybe should force stop bob, but should be all
stopped by _release by now */
/* Turn off hardware volume control interrupt.
This has to come before we leave the IRQ below,
or a crash results if a button is pressed ! */
n
=
inw
(
card
->
iobase
+
0x18
);
n
&=~
(
1
<<
6
);
outw
(
n
,
card
->
iobase
+
0x18
);
free_irq
(
card
->
irq
,
card
);
unregister_sound_mixer
(
card
->
dev_mixer
);
for
(
i
=
0
;
i
<
NR_DSPS
;
i
++
)
...
...
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