Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
5d278332
Commit
5d278332
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 1.1.94
parent
fde9fa96
Changes
42
Hide whitespace changes
Inline
Side-by-side
Showing
42 changed files
with
1098 additions
and
570 deletions
+1098
-570
Makefile
Makefile
+1
-1
arch/alpha/kernel/entry.S
arch/alpha/kernel/entry.S
+12
-0
arch/alpha/kernel/process.c
arch/alpha/kernel/process.c
+50
-8
arch/alpha/kernel/traps.c
arch/alpha/kernel/traps.c
+19
-0
arch/i386/kernel/process.c
arch/i386/kernel/process.c
+22
-11
arch/i386/kernel/ptrace.c
arch/i386/kernel/ptrace.c
+27
-4
arch/sparc/mm/fault.c
arch/sparc/mm/fault.c
+0
-5
arch/sparc/mm/init.c
arch/sparc/mm/init.c
+2
-2
drivers/block/sonycd535.c
drivers/block/sonycd535.c
+321
-186
drivers/char/ChangeLog
drivers/char/ChangeLog
+72
-0
drivers/char/n_tty.c
drivers/char/n_tty.c
+12
-1
drivers/char/selection.c
drivers/char/selection.c
+7
-4
drivers/char/selection.h
drivers/char/selection.h
+5
-3
drivers/char/serial.c
drivers/char/serial.c
+238
-84
drivers/char/tty_io.c
drivers/char/tty_io.c
+3
-0
drivers/net/README.wavelan
drivers/net/README.wavelan
+3
-21
drivers/net/wavelan.c
drivers/net/wavelan.c
+27
-17
fs/buffer.c
fs/buffer.c
+1
-1
fs/isofs/dir.c
fs/isofs/dir.c
+11
-8
fs/isofs/inode.c
fs/isofs/inode.c
+8
-0
fs/isofs/namei.c
fs/isofs/namei.c
+0
-11
fs/locks.c
fs/locks.c
+31
-48
fs/proc/mem.c
fs/proc/mem.c
+57
-42
include/asm-alpha/byteorder.h
include/asm-alpha/byteorder.h
+8
-14
include/asm-alpha/pgtable.h
include/asm-alpha/pgtable.h
+15
-0
include/asm-i386/byteorder.h
include/asm-i386/byteorder.h
+8
-14
include/asm-sparc/system.h
include/asm-sparc/system.h
+2
-0
include/asm-sparc/vac-ops.h
include/asm-sparc/vac-ops.h
+2
-2
include/linux/fs.h
include/linux/fs.h
+3
-2
include/linux/iso_fs_sb.h
include/linux/iso_fs_sb.h
+1
-0
include/linux/sched.h
include/linux/sched.h
+2
-1
include/linux/serial.h
include/linux/serial.h
+46
-2
include/linux/serial_reg.h
include/linux/serial_reg.h
+24
-0
include/linux/sys.h
include/linux/sys.h
+0
-5
include/linux/termios.h
include/linux/termios.h
+3
-0
include/linux/tty.h
include/linux/tty.h
+1
-0
ipc/shm.c
ipc/shm.c
+26
-53
kernel/fork.c
kernel/fork.c
+3
-4
kernel/sys.c
kernel/sys.c
+1
-0
mm/swap.c
mm/swap.c
+18
-14
net/inet/af_inet.c
net/inet/af_inet.c
+2
-0
net/inet/tcp.c
net/inet/tcp.c
+4
-2
No files found.
Makefile
View file @
5d278332
VERSION
=
1
PATCHLEVEL
=
1
SUBLEVEL
=
9
3
SUBLEVEL
=
9
4
ARCH
=
i386
...
...
arch/alpha/kernel/entry.S
View file @
5d278332
...
...
@@ -145,6 +145,18 @@ entUna:
rti
.
end
entUna
.
align
5
.
globl
entSys
.
ent
entSys
entSys
:
SAVE_ALL
bis
$
30
,
$
30
,
$
19
lda
$
27
,
do_entSys
jsr
$
26
,(
$
27
),
do_entSys
RESTORE_ALL
rti
.
end
entSys
.
align
5
.
globl
sys_call_table
sys_call_table
:
...
...
arch/alpha/kernel/process.c
View file @
5d278332
...
...
@@ -60,19 +60,19 @@ void flush_thread(void)
}
/*
* This needs
lots of
work still..
* This needs
some
work still..
*/
unsigned
long
copy_thread
(
int
nr
,
unsigned
long
clone_flags
,
struct
task_struct
*
p
,
struct
pt_regs
*
regs
)
void
copy_thread
(
int
nr
,
unsigned
long
clone_flags
,
unsigned
long
usp
,
struct
task_struct
*
p
,
struct
pt_regs
*
regs
)
{
struct
pt_regs
*
childregs
;
p
->
tss
.
usp
=
rdusp
()
;
p
->
tss
.
usp
=
usp
;
childregs
=
((
struct
pt_regs
*
)
(
p
->
kernel_stack_page
+
PAGE_SIZE
))
-
1
;
*
childregs
=
*
regs
;
p
->
tss
.
ksp
=
(
unsigned
long
)
childregs
;
/* p->tss.pc = XXXX; */
halt
();
return
clone_flags
;
panic
(
"copy_thread not implemented"
);
}
/*
...
...
@@ -84,9 +84,51 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
/*
* sys_execve() executes a new program.
*
* This works due to the alpha calling sequence: the first 6 args
* are gotten from registers, while the rest is on the stack, so
* we get a0-a5 for free, and then magically find "struct pt_regs"
* on the stack for us..
*
* Don't do this at home.
*/
asmlinkage
int
sys_execve
(
struct
pt_regs
regs
)
asmlinkage
int
sys_execve
(
unsigned
long
a0
,
unsigned
long
a1
,
unsigned
long
a2
,
unsigned
long
a3
,
unsigned
long
a4
,
unsigned
long
a5
,
struct
pt_regs
regs
)
{
halt
();
return
0
;
int
error
;
char
*
filename
;
error
=
getname
((
char
*
)
a0
,
&
filename
);
if
(
error
)
return
error
;
error
=
do_execve
(
filename
,
(
char
**
)
a1
,
(
char
**
)
a2
,
&
regs
);
putname
(
filename
);
return
error
;
}
/*
* sys_fork() does the obvious thing, but not the obvious way.
* See sys_execve() above.
*/
asmlinkage
int
sys_fork
(
unsigned
long
a0
,
unsigned
long
a1
,
unsigned
long
a2
,
unsigned
long
a3
,
unsigned
long
a4
,
unsigned
long
a5
,
struct
pt_regs
regs
)
{
return
do_fork
(
COPYVM
|
SIGCHLD
,
rdusp
(),
&
regs
);
}
asmlinkage
int
sys_clone
(
unsigned
long
a0
,
unsigned
long
a1
,
unsigned
long
a2
,
unsigned
long
a3
,
unsigned
long
a4
,
unsigned
long
a5
,
struct
pt_regs
regs
)
{
unsigned
long
clone_flags
=
a0
;
unsigned
long
newsp
;
newsp
=
rdusp
();
if
(
newsp
==
a1
||
!
a1
)
clone_flags
|=
COPYVM
;
else
newsp
=
a1
;
return
do_fork
(
clone_flags
,
newsp
,
&
regs
);
}
arch/alpha/kernel/traps.c
View file @
5d278332
...
...
@@ -38,10 +38,28 @@ asmlinkage void do_entUna(unsigned long va, unsigned long opcode, unsigned long
die_if_kernel
(
"Unaligned"
,
regs
,
0
);
}
/*
* DEC means people to use the "retsys" instruction for return from
* a system call, but they are clearly misguided about this. We use
* "rti" in all cases, and fill in the stack with the return values.
* That should make signal handling etc much cleaner.
*
* Even more horribly, DEC doesn't allow system calls from kernel mode.
* "Security" features letting the user do something the kernel can't
* are a thinko. DEC palcode is strange. The PAL-code designers probably
* got terminally tainted by VMS at some point.
*/
asmlinkage
void
do_entSys
(
unsigned
long
sysnr
,
unsigned
long
arg1
,
unsigned
long
arg2
,
struct
pt_regs
*
regs
)
{
printk
(
"System call %ld(%ld,%ld)
\n
"
,
sysnr
,
arg1
,
arg2
);
die_if_kernel
(
"Syscall"
,
regs
,
0
);
}
extern
asmlinkage
void
entMM
(
void
);
extern
asmlinkage
void
entIF
(
void
);
extern
asmlinkage
void
entArith
(
void
);
extern
asmlinkage
void
entUna
(
void
);
extern
asmlinkage
void
entSys
(
void
);
void
trap_init
(
void
)
{
...
...
@@ -59,4 +77,5 @@ void trap_init(void)
wrent
(
entMM
,
2
);
wrent
(
entIF
,
3
);
wrent
(
entUna
,
4
);
wrent
(
entSys
,
5
);
}
arch/i386/kernel/process.c
View file @
5d278332
...
...
@@ -150,9 +150,8 @@ void flush_thread(void)
current
->
debugreg
[
i
]
=
0
;
}
#define IS_CLONE (regs->orig_eax == __NR_clone)
unsigned
long
copy_thread
(
int
nr
,
unsigned
long
clone_flags
,
struct
task_struct
*
p
,
struct
pt_regs
*
regs
)
void
copy_thread
(
int
nr
,
unsigned
long
clone_flags
,
unsigned
long
esp
,
struct
task_struct
*
p
,
struct
pt_regs
*
regs
)
{
int
i
;
struct
pt_regs
*
childregs
;
...
...
@@ -171,15 +170,9 @@ unsigned long copy_thread(int nr, unsigned long clone_flags, struct task_struct
p
->
tss
.
eip
=
(
unsigned
long
)
ret_from_sys_call
;
*
childregs
=
*
regs
;
childregs
->
eax
=
0
;
childregs
->
esp
=
esp
;
p
->
tss
.
back_link
=
0
;
p
->
tss
.
eflags
=
regs
->
eflags
&
0xffffcfff
;
/* iopl is always 0 for a new process */
if
(
IS_CLONE
)
{
if
(
regs
->
ebx
)
childregs
->
esp
=
regs
->
ebx
;
clone_flags
=
regs
->
ecx
;
if
(
childregs
->
esp
==
regs
->
esp
)
clone_flags
|=
COPYVM
;
}
p
->
tss
.
ldt
=
_LDT
(
nr
);
if
(
p
->
ldt
)
{
p
->
ldt
=
(
struct
desc_struct
*
)
vmalloc
(
LDT_ENTRIES
*
LDT_ENTRY_SIZE
);
...
...
@@ -196,7 +189,6 @@ unsigned long copy_thread(int nr, unsigned long clone_flags, struct task_struct
p
->
tss
.
io_bitmap
[
i
]
=
~
0
;
if
(
last_task_used_math
==
current
)
__asm__
(
"clts ; fnsave %0 ; frstor %0"
:
"=m"
(
p
->
tss
.
i387
));
return
clone_flags
;
}
/*
...
...
@@ -238,6 +230,25 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
}
}
asmlinkage
int
sys_fork
(
struct
pt_regs
regs
)
{
return
do_fork
(
COPYVM
|
SIGCHLD
,
regs
.
esp
,
&
regs
);
}
asmlinkage
int
sys_clone
(
struct
pt_regs
regs
)
{
unsigned
long
clone_flags
;
unsigned
long
newsp
;
newsp
=
regs
.
ebx
;
clone_flags
=
regs
.
ecx
;
if
(
!
newsp
)
newsp
=
regs
.
esp
;
if
(
newsp
==
regs
.
esp
)
clone_flags
|=
COPYVM
;
return
do_fork
(
clone_flags
,
newsp
,
&
regs
);
}
/*
* sys_execve() executes a new program.
*/
...
...
arch/i386/kernel/ptrace.c
View file @
5d278332
#define THREE_LEVEL
/* ptrace.c */
/* By Ross Biro 1/23/92 */
/* edited by Linus Torvalds */
...
...
@@ -86,11 +87,12 @@ static inline int put_stack_long(struct task_struct *task, int offset,
static
unsigned
long
get_long
(
struct
vm_area_struct
*
vma
,
unsigned
long
addr
)
{
pgd_t
*
pgdir
;
pmd_t
*
pgmiddle
;
pte_t
*
pgtable
;
unsigned
long
page
;
repeat:
pgdir
=
PAGE_DIR_OFFSET
(
vma
->
vm_task
,
addr
);
pgdir
=
pgd_offset
(
vma
->
vm_task
,
addr
);
if
(
pgd_none
(
*
pgdir
))
{
do_no_page
(
vma
,
addr
,
0
);
goto
repeat
;
...
...
@@ -100,7 +102,17 @@ static unsigned long get_long(struct vm_area_struct * vma, unsigned long addr)
pgd_clear
(
pgdir
);
return
0
;
}
pgtable
=
(
pte_t
*
)
(
PAGE_PTR
(
addr
)
+
pgd_page
(
*
pgdir
));
pgmiddle
=
pmd_offset
(
pgdir
,
addr
);
if
(
pmd_none
(
*
pgmiddle
))
{
do_no_page
(
vma
,
addr
,
0
);
goto
repeat
;
}
if
(
pmd_bad
(
*
pgmiddle
))
{
printk
(
"ptrace: bad page middle %08lx
\n
"
,
pmd_val
(
*
pgmiddle
));
pmd_clear
(
pgmiddle
);
return
0
;
}
pgtable
=
pte_offset
(
pgmiddle
,
addr
);
if
(
!
pte_present
(
*
pgtable
))
{
do_no_page
(
vma
,
addr
,
0
);
goto
repeat
;
...
...
@@ -126,11 +138,12 @@ static void put_long(struct vm_area_struct * vma, unsigned long addr,
unsigned
long
data
)
{
pgd_t
*
pgdir
;
pmd_t
*
pgmiddle
;
pte_t
*
pgtable
;
unsigned
long
page
;
repeat:
pgdir
=
PAGE_DIR_OFFSET
(
vma
->
vm_task
,
addr
);
pgdir
=
pgd_offset
(
vma
->
vm_task
,
addr
);
if
(
!
pgd_present
(
*
pgdir
))
{
do_no_page
(
vma
,
addr
,
1
);
goto
repeat
;
...
...
@@ -140,7 +153,17 @@ static void put_long(struct vm_area_struct * vma, unsigned long addr,
pgd_clear
(
pgdir
);
return
;
}
pgtable
=
(
pte_t
*
)
(
PAGE_PTR
(
addr
)
+
pgd_page
(
*
pgdir
));
pgmiddle
=
pmd_offset
(
pgdir
,
addr
);
if
(
pmd_none
(
*
pgmiddle
))
{
do_no_page
(
vma
,
addr
,
0
);
goto
repeat
;
}
if
(
pmd_bad
(
*
pgmiddle
))
{
printk
(
"ptrace: bad page middle %08lx
\n
"
,
pmd_val
(
*
pgmiddle
));
pmd_clear
(
pgmiddle
);
return
;
}
pgtable
=
pte_offset
(
pgmiddle
,
addr
);
if
(
!
pte_present
(
*
pgtable
))
{
do_no_page
(
vma
,
addr
,
1
);
goto
repeat
;
...
...
arch/sparc/mm/fault.c
View file @
5d278332
...
...
@@ -14,11 +14,6 @@
extern
unsigned
long
pg0
[
1024
];
/* page table for 0-4MB for everybody */
extern
void
die_if_kernel
(
char
*
,
struct
pt_regs
*
,
long
);
/* Sparc stuff... I know this is a ugly place to put the PROM vector, don't
* remind me.
*/
extern
unsigned
int
trapbase
[];
extern
unsigned
int
end
[],
etext
[],
msgbuf
[];
struct
linux_romvec
*
romvec
;
/* foo */
...
...
arch/sparc/mm/init.c
View file @
5d278332
...
...
@@ -160,7 +160,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
* self-modifying code.
*/
a
=
(
unsigned
long
)
etext
;
a
=
(
unsigned
long
)
&
etext
;
mask
=~
(
PTE_NC
|
PTE_W
);
/* make cacheable + not writable */
printk
(
"changing kernel text perms...
\n
"
);
...
...
@@ -173,7 +173,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
for
(
i
=
0
;
i
<
8
;
i
++
)
{
b
=
PAGE_ALIGN
((
unsigned
long
)
trapbase
);
b
=
PAGE_ALIGN
((
unsigned
long
)
&
trapbase
);
switch_to_context
(
i
);
...
...
drivers/block/sonycd535.c
View file @
5d278332
...
...
@@ -4,7 +4,7 @@
* This is a modified version of the CDU-31A device driver (see below).
* Changes were made using documentation for the CDU-531 (which Sony
* assures me is very similar to the 535) and partial disassembly of the
* DOS driver. I used Minyard's driver and replaced the the CDU-31A
* DOS driver. I used Minyard's driver and replaced the the CDU-31A
* commands with the CDU-531 commands. This was complicated by a different
* interface protocol with the drive. The driver is still polled.
*
...
...
@@ -23,18 +23,23 @@
*
* Things to do:
* - handle errors and status better, put everything into a single word
* - use interrupts, DMA
* - use interrupts (code mostly there, but a big hole still missing)
* - handle multi-session CDs?
* - use DMA?
*
* Known Bugs:
* -
*
* Ken Pizzini (ken@halcyon.com)
*
* Original by:
* Ron Jeppesen (ronj.an@site007.saic.com)
*
*
*------------------------------------------------------------------------
* Sony CDROM interface device driver.
*
* Corey Minyard (minyard@wf-rch.cirr.com) (CDU-535 complaints to
ronj
above)
* Corey Minyard (minyard@wf-rch.cirr.com) (CDU-535 complaints to
Ken
above)
*
* Colossians 3:17
*
...
...
@@ -99,6 +104,9 @@
# include <linux/module.h>
# include <linux/malloc.h>
# include <linux/version.h>
# ifndef CONFIG_MODVERSIONS
char
kernel_version
[]
=
UTS_RELEASE
;
# endif
#endif
#include <linux/errno.h>
...
...
@@ -137,9 +145,11 @@
* proper address.
*/
#ifndef CDU535_ADDRESS
# define CDU535_ADDRESS (0x340)
# define CDU535_ADDRESS 0x340
#endif
#ifndef CDU535_INTERRUPT
# define CDU535_INTERRUPT 0
#endif
#ifndef CDU535_HANDLE
# define CDU535_HANDLE "cdu535"
#endif
...
...
@@ -171,7 +181,9 @@
* if LOCK_DOORS is defined then the eject button is disabled while
* the device is open.
*/
#define LOCK_DOORS
#ifndef NO_LOCK_DOORS
# define LOCK_DOORS
#endif
static
int
read_subcode
(
void
);
static
void
sony_get_toc
(
void
);
...
...
@@ -179,11 +191,14 @@ static int cdu_open(struct inode *inode, struct file *filp);
static
inline
unsigned
int
int_to_bcd
(
unsigned
int
val
);
static
unsigned
int
bcd_to_int
(
unsigned
int
bcd
);
static
int
do_sony_cmd
(
Byte
*
cmd
,
int
nCmd
,
Byte
status
[
2
],
Byte
*
response
,
int
n
R
esponse
,
int
ignoreStatusBit7
);
Byte
*
response
,
int
n
_r
esponse
,
int
ignoreStatusBit7
);
/* The base I/O address of the Sony Interface. This is a variable (not a
#define) so it can be easily changed via some future ioctl() */
static
unsigned
short
sony_cd_base_io
=
CDU535_ADDRESS
;
#ifndef MODULE
static
#endif
unsigned
short
sony535_cd_base_io
=
CDU535_ADDRESS
;
/*
* The following are I/O addresses of the various registers for the drive. The
...
...
@@ -217,10 +232,10 @@ static struct s535_sony_toc *sony_toc; /* Points to the table of
static
struct
s535_sony_subcode
*
last_sony_subcode
;
/* Points to the last
subcode address read */
#ifndef MODULE
static
unsigned
char
*
sony_buffer
;
/* Points to the read-ahead buffer */
static
Byte
*
sony_buffer
;
/* Points to the read-ahead buffer */
#else
static
unsigned
char
**
sony_buffer
;
/* Points to the pointers
to the sector buffers */
static
Byte
**
sony_buffer
;
/* Points to the pointers
to the sector buffers */
#endif
static
int
sony_inuse
=
0
;
/* is the drive in use? Only one
open at a time allowed */
...
...
@@ -240,8 +255,17 @@ static int sony_audio_status = CDROM_AUDIO_NO_STATUS;
* I just kept the CDU-31A driver behavior rather than using the PAUSE
* command on the CDU-535.
*/
static
unsigned
char
cur_pos_msf
[
3
]
=
{
0
,
0
,
0
};
static
unsigned
char
final_pos_msf
[
3
]
=
{
0
,
0
,
0
};
static
Byte
cur_pos_msf
[
3
]
=
{
0
,
0
,
0
};
static
Byte
final_pos_msf
[
3
]
=
{
0
,
0
,
0
};
/* What IRQ is the drive using? 0 if none. */
#ifndef MODULE
static
#endif
int
sony535_irq_used
=
CDU535_INTERRUPT
;
/* The interrupt handler will wake this queue up when it gets an interrupt. */
static
struct
wait_queue
*
cdu535_irq_wait
=
NULL
;
/*
...
...
@@ -251,10 +275,10 @@ static unsigned char final_pos_msf[3] = {0, 0, 0};
static
int
cdu535_check_media_change
(
dev_t
full_dev
)
{
int
retval
;
int
retval
;
if
(
MINOR
(
full_dev
)
!=
0
)
{
printk
(
"Sony CD-ROM
request error: invalid device.
\n
"
);
printk
(
CDU535_MESSAGE_NAME
"
request error: invalid device.
\n
"
);
return
0
;
}
...
...
@@ -264,18 +288,64 @@ cdu535_check_media_change(dev_t full_dev)
return
retval
;
}
static
inline
void
enable_interrupts
(
void
)
{
#ifdef USE_IRQ
/* this code snarfed from cdu31a.c; it will not
* directly work for the cdu535 as written...
*/
curr_control_reg
|=
(
SONY_ATTN_INT_EN_BIT
|
SONY_RES_RDY_INT_EN_BIT
|
SONY_DATA_RDY_INT_EN_BIT
);
outb
(
curr_control_reg
,
sony_cd_control_reg
);
#endif
}
static
inline
void
disable_interrupts
(
void
)
{
#ifdef USE_IRQ
/* this code snarfed from cdu31a.c; it will not
* directly work for the cdu535 as written...
*/
curr_control_reg
&=
~
(
SONY_ATTN_INT_EN_BIT
|
SONY_RES_RDY_INT_EN_BIT
|
SONY_DATA_RDY_INT_EN_BIT
);
outb
(
curr_control_reg
,
sony_cd_control_reg
);
#endif
}
static
void
cdu535_interrupt
(
int
irq
,
struct
pt_regs
*
regs
)
{
disable_interrupts
();
if
(
cdu535_irq_wait
!=
NULL
)
wake_up
(
&
cdu535_irq_wait
);
else
printk
(
CDU535_MESSAGE_NAME
": Got an interrupt but nothing was waiting
\n
"
);
}
/*
* Wait a little while (used for polling the drive). If in initialization,
* setting a timeout doesn't work, so just loop for a while
(w
e trust
* that the sony_sleep() call is protected by a test for proper jiffies count
).
* setting a timeout doesn't work, so just loop for a while
. (W
e trust
* that the sony_sleep() call is protected by a test for proper jiffies count
.)
*/
static
inline
void
sony_sleep
(
void
)
{
current
->
state
=
TASK_INTERRUPTIBLE
;
current
->
timeout
=
jiffies
;
schedule
();
if
(
sony535_irq_used
<=
0
)
{
/* poll */
current
->
state
=
TASK_INTERRUPTIBLE
;
current
->
timeout
=
jiffies
;
schedule
();
}
else
{
/* Interrupt driven */
cli
();
enable_interrupts
();
interruptible_sleep_on
(
&
cdu535_irq_wait
);
sti
();
}
}
/*------------------start of SONY CDU535 very specific ---------------------*/
...
...
@@ -293,23 +363,24 @@ select_unit(int unit_no)
}
/***************************************************************************
* int read_result_reg(
unsigned char
*data_ptr )
* int read_result_reg(
Byte
*data_ptr )
*
* Read a result byte from the Sony CDU controller, store in location pointed
* to by data_ptr. Return zero on success, TIME_OUT if we did not receive
* data.
***************************************************************************/
static
int
read_result_reg
(
unsigned
char
*
data_ptr
)
read_result_reg
(
Byte
*
data_ptr
)
{
int
retry_count
;
int
read_status
;
int
retry_count
;
int
read_status
;
retry_count
=
jiffies
+
SONY_JIFFIES_TIMEOUT
;
while
(
jiffies
<
retry_count
)
{
if
(((
read_status
=
inb
(
read_status_reg
))
&
SONY535_RESULT_NOT_READY_BIT
)
==
0
)
{
#if DEBUG > 1
printk
(
"read_result_reg(): readStatReg = 0x%x
\n
"
,
read_status
);
printk
(
CDU535_MESSAGE_NAME
": read_result_reg(): readStatReg = 0x%x
\n
"
,
read_status
);
#endif
*
data_ptr
=
inb
(
result_reg
);
return
0
;
...
...
@@ -317,14 +388,14 @@ read_result_reg(unsigned char *data_ptr)
sony_sleep
();
}
}
printk
(
" Sony CDROM
read_result_reg: TIME OUT!
\n
"
);
printk
(
CDU535_MESSAGE_NAME
"
read_result_reg: TIME OUT!
\n
"
);
return
TIME_OUT
;
}
/****************************************************************************
* int read_exec_status( Byte status[2] )
*
* Read the execution status of the last command and put into status.
* Read the execution status of the last command and put into status.
* Handles reading second status word if available. Returns 0 on success,
* TIME_OUT on failure.
****************************************************************************/
...
...
@@ -339,10 +410,8 @@ read_exec_status(Byte status[2])
return
TIME_OUT
;
}
#if DEBUG > 1
printk
(
"read_exec_status: read 0x%x
\n
"
,
status
[
0
]);
if
(
status
[
0
]
&
0x80
)
printk
(
" and 0x%x
\n
"
,
status
[
1
]);
printk
(
"
\n
"
);
printk
(
CDU535_MESSAGE_NAME
": read_exec_status: read 0x%x 0x%x
\n
"
,
status
[
0
],
status
[
1
]);
#endif
return
0
;
}
...
...
@@ -357,9 +426,9 @@ read_exec_status(Byte status[2])
static
int
check_drive_status
(
void
)
{
Byte
status
,
e_status
[
2
];
int
CDD
,
ATN
;
unsigned
char
cmd
;
Byte
status
,
e_status
[
2
];
int
CDD
,
ATN
;
Byte
cmd
;
select_unit
(
0
);
if
(
sony_audio_status
==
CDROM_AUDIO_PLAY
)
{
/* check status */
...
...
@@ -387,7 +456,7 @@ check_drive_status(void)
return
TIME_OUT
;
#if DEBUG > 1
printk
(
"--
check_drive_status() got 0x%x
\n
"
,
status
);
printk
(
CDU535_MESSAGE_NAME
":
check_drive_status() got 0x%x
\n
"
,
status
);
#endif
if
(
status
==
0
)
...
...
@@ -401,17 +470,17 @@ check_drive_status(void)
break
;
/* go on to CDD stuff */
case
SONY535_ATN_BUSY
:
if
(
initialized
)
printk
(
"Sony CDROM error,
drive busy
\n
"
);
printk
(
CDU535_MESSAGE_NAME
" error:
drive busy
\n
"
);
return
CD_BUSY
;
case
SONY535_ATN_EJECT_IN_PROGRESS
:
printk
(
"Sony CDROM error,
eject in progress
\n
"
);
printk
(
CDU535_MESSAGE_NAME
" error:
eject in progress
\n
"
);
sony_audio_status
=
CDROM_AUDIO_INVALID
;
return
CD_BUSY
;
case
SONY535_ATN_RESET_OCCURRED
:
case
SONY535_ATN_DISC_CHANGED
:
case
SONY535_ATN_RESET_AND_DISC_CHANGED
:
#if DEBUG > 0
printk
(
"Sony CDROM,
reset occurred or disc changed
\n
"
);
printk
(
CDU535_MESSAGE_NAME
" notice:
reset occurred or disc changed
\n
"
);
#endif
sony_disc_changed
=
1
;
sony_toc_read
=
0
;
...
...
@@ -425,16 +494,17 @@ check_drive_status(void)
}
return
0
;
default:
printk
(
"Sony CDROM error,
drive busy (ATN=0x%x)
\n
"
,
ATN
);
printk
(
CDU535_MESSAGE_NAME
" error:
drive busy (ATN=0x%x)
\n
"
,
ATN
);
return
CD_BUSY
;
}
switch
(
CDD
)
{
/* the 531 docs are not helpful in decoding this */
case
0x0
:
/* just use the values from the DOS driver */
switch
(
CDD
)
{
/* the 531 docs are not helpful in decoding this */
case
0x0
:
/* just use the values from the DOS driver */
case
0x2
:
case
0xa
:
break
;
/* no error */
break
;
/* no error */
case
0xc
:
printk
(
"check_drive_status(): CDD = 0xc! Not properly handled!
\n
"
);
printk
(
CDU535_MESSAGE_NAME
": check_drive_status(): CDD = 0xc! Not properly handled!
\n
"
);
return
CD_BUSY
;
/* ? */
default:
return
CD_BUSY
;
...
...
@@ -443,14 +513,14 @@ check_drive_status(void)
}
/* check_drive_status() */
/*****************************************************************************
* int do_sony_cmd( Byte *cmd, int n_cmd, Byte status[2],
* int do_sony_cmd( Byte *cmd, int n_cmd, Byte status[2],
* Byte *response, int n_response, int ignore_status_bit7 )
*
* Generic routine for executing commands. The command and its parameters
* should be placed in the cmd[] array, number of bytes in the command is
* stored in nCmd. The response from the command will be stored in the
* response array. The number of bytes you expect back (excluding status)
* should be passed in n
R
esponse. Finally, some
* should be passed in n
_r
esponse. Finally, some
* commands set bit 7 of the return status even when there is no second
* status byte, on these commands set ignoreStatusBit7 TRUE.
* If the command was sent and data received back, then we return 0,
...
...
@@ -462,7 +532,7 @@ static int
do_sony_cmd
(
Byte
*
cmd
,
int
n_cmd
,
Byte
status
[
2
],
Byte
*
response
,
int
n_response
,
int
ignore_status_bit7
)
{
int
i
;
int
i
;
/* write out the command */
for
(
i
=
0
;
i
<
n_cmd
;
i
++
)
...
...
@@ -471,7 +541,7 @@ do_sony_cmd(Byte * cmd, int n_cmd, Byte status[2],
/* read back the status */
if
(
read_result_reg
(
status
)
!=
0
)
return
TIME_OUT
;
if
(
!
ignore_status_bit7
&&
((
status
[
0
]
&
0x80
)
!=
0
))
{
if
(
!
ignore_status_bit7
&&
((
status
[
0
]
&
0x80
)
!=
0
))
{
/* get second status byte */
if
(
read_result_reg
(
status
+
1
)
!=
0
)
return
TIME_OUT
;
...
...
@@ -479,7 +549,8 @@ do_sony_cmd(Byte * cmd, int n_cmd, Byte status[2],
status
[
1
]
=
0
;
}
#if DEBUG > 2
printk
(
"do_sony_cmd %x: %x %x
\n
"
,
*
cmd
,
status
[
0
],
status
[
1
]);
printk
(
CDU535_MESSAGE_NAME
": do_sony_cmd %x: %x %x
\n
"
,
*
cmd
,
status
[
0
],
status
[
1
]);
#endif
/* do not know about when I should read set of data and when not to */
...
...
@@ -502,7 +573,8 @@ do_sony_cmd(Byte * cmd, int n_cmd, Byte status[2],
static
int
set_drive_mode
(
int
mode
,
Byte
status
[
2
])
{
Byte
cmd_buff
[
2
],
ret_buff
[
1
];
Byte
cmd_buff
[
2
];
Byte
ret_buff
[
1
];
cmd_buff
[
0
]
=
SONY535_SET_DRIVE_MODE
;
cmd_buff
[
1
]
=
mode
;
...
...
@@ -510,7 +582,7 @@ set_drive_mode(int mode, Byte status[2])
}
/***************************************************************************
* int seek_and_read_N_blocks( Byte params[], int n_blocks, Byte status[2],
* int seek_and_read_N_blocks( Byte params[], int n_blocks, Byte status[2],
* Byte *data_buff, int buff_size )
*
* Read n_blocks of data from the CDROM starting at position params[0:2],
...
...
@@ -527,19 +599,19 @@ seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
Byte
*
data_buff
,
int
buf_size
)
#else
seek_and_read_N_blocks
(
Byte
params
[],
int
n_blocks
,
Byte
status
[
2
],
unsigned
char
**
buff
,
int
buf_size
)
Byte
**
buff
,
int
buf_size
)
#endif
{
int
i
;
const
int
block_size
=
2048
;
Byte
cmd_buff
[
7
];
int
read_status
;
int
retry_count
;
#ifdef MODULE
Byte
*
data_buff
;
int
sector_count
=
0
;
Byte
cmd_buff
[
7
];
int
i
;
int
read_status
;
int
retry_count
;
#ifndef MODULE
Byte
*
start_pos
=
data_buff
;
#else
Byte
*
start_pos
=
data_buff
;
Byte
*
data_buff
;
int
sector_count
=
0
;
#endif
if
(
buf_size
<
((
long
)
block_size
)
*
n_blocks
)
...
...
@@ -598,11 +670,11 @@ seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
static
int
request_toc_data
(
Byte
status
[
2
],
struct
s535_sony_toc
*
toc
)
{
int
to_status
;
int
i
,
j
,
n_tracks
,
track_no
;
Byte
cmd_no
=
0xb2
;
Byte
track_address_buffer
[
5
]
;
int
first_track_num
,
last_track_num
;
int
to_status
;
int
i
,
j
,
n_tracks
,
track_no
;
int
first_track_num
,
last_track_num
;
Byte
cmd_no
=
0xb2
;
Byte
track_address_buffer
[
5
]
;
/* read the fixed portion of the table of contents */
if
((
to_status
=
do_sony_cmd
(
&
cmd_no
,
1
,
status
,
(
Byte
*
)
toc
,
15
,
1
))
!=
0
)
...
...
@@ -636,19 +708,19 @@ request_toc_data(Byte status[2], struct s535_sony_toc *toc)
static
int
spin_up_drive
(
Byte
status
[
2
])
{
Byte
cmd_buff
[
1
]
;
Byte
cmd
;
/* first see if the drive is already spinning */
cmd
_buff
[
0
]
=
SONY535_REQUEST_DRIVE_STATUS_1
;
if
(
do_sony_cmd
(
cmd_buff
,
1
,
status
,
NULL
,
0
,
0
)
!=
0
)
cmd
=
SONY535_REQUEST_DRIVE_STATUS_1
;
if
(
do_sony_cmd
(
&
cmd
,
1
,
status
,
NULL
,
0
,
0
)
!=
0
)
return
TIME_OUT
;
if
((
status
[
0
]
&
SONY535_STATUS1_NOT_SPINNING
)
==
0
)
return
0
;
/* its already spinning */
return
0
;
/* its already spinning */
/*
el
se, give the spin-up command */
cmd
_buff
[
0
]
=
SONY535_SPIN_UP
;
return
do_sony_cmd
(
cmd_buff
,
1
,
status
,
NULL
,
0
,
0
);
}
/* spin_up_drive() */
/*
otherwi
se, give the spin-up command */
cmd
=
SONY535_SPIN_UP
;
return
do_sony_cmd
(
&
cmd
,
1
,
status
,
NULL
,
0
,
0
);
}
/*--------------------end of SONY CDU535 very specific ---------------------*/
...
...
@@ -656,8 +728,7 @@ spin_up_drive(Byte status[2])
static
inline
unsigned
int
int_to_bcd
(
unsigned
int
val
)
{
int
retval
;
int
retval
;
retval
=
(
val
/
10
)
<<
4
;
retval
=
retval
|
val
%
10
;
...
...
@@ -678,7 +749,7 @@ bcd_to_int(unsigned int bcd)
* a block device) to an MSF format.
*/
static
void
log_to_msf
(
unsigned
int
log
,
unsigned
char
*
msf
)
log_to_msf
(
unsigned
int
log
,
Byte
*
msf
)
{
log
=
log
+
LOG_START_OFFSET
;
msf
[
0
]
=
int_to_bcd
(
log
/
4500
);
...
...
@@ -692,7 +763,7 @@ log_to_msf(unsigned int log, unsigned char *msf)
* Convert an MSF format to a logical sector.
*/
static
unsigned
int
msf_to_log
(
unsigned
char
*
msf
)
msf_to_log
(
Byte
*
msf
)
{
unsigned
int
log
;
...
...
@@ -711,8 +782,7 @@ msf_to_log(unsigned char *msf)
* the drive would want to see a number-of-sector value.
*/
static
void
size_to_buf
(
unsigned
int
size
,
unsigned
char
*
buf
)
size_to_buf
(
unsigned
int
size
,
Byte
*
buf
)
{
buf
[
0
]
=
size
/
65536
;
size
=
size
%
65536
;
...
...
@@ -731,14 +801,15 @@ size_to_buf(unsigned int size,
static
void
do_cdu535_request
(
void
)
{
int
block
;
unsigned
int
dev
;
int
nsect
;
unsigned
char
params
[
10
];
int
copyoff
;
int
spin_up_retry
;
unsigned
int
read_size
;
unsigned
char
status
[
2
],
cmd
[
2
];
int
block
;
int
nsect
;
int
copyoff
;
int
spin_up_retry
;
Byte
params
[
10
];
Byte
status
[
2
];
Byte
cmd
[
2
];
if
(
!
sony_inuse
)
{
...
...
@@ -798,33 +869,37 @@ do_cdu535_request(void)
size_to_buf
(
read_size
,
&
params
[
3
]);
/*
* Read the data. If the drive was not spinning,
spin it up and try
*
once more. I know, the goto is ugly, but I am too lazy to fix it
.
* Read the data. If the drive was not spinning,
*
spin it up and try once more
.
*/
spin_up_retry
=
0
;
try_read_again:
for
(;;)
{
#if DEBUG > 1
if
(
check_drive_status
()
!=
0
)
{
/* drive not ready */
sony_first_block
=
-
1
;
sony_last_block
=
-
1
;
end_request
(
0
);
return
;
}
if
(
check_drive_status
()
!=
0
)
{
/* drive not ready */
sony_first_block
=
-
1
;
sony_last_block
=
-
1
;
end_request
(
0
);
return
;
}
#endif
if
(
seek_and_read_N_blocks
(
params
,
read_size
,
status
,
sony_buffer
,
(
read_size
*
2048
))
<
0
)
{
if
((
status
[
0
]
&
SONY535_STATUS1_NOT_SPINNING
)
&&
(
!
spin_up_retry
))
{
printk
(
" Sony535 Debug -- calling spin up when reading data!
\n
"
);
cmd
[
0
]
=
SONY535_SPIN_UP
;
do_sony_cmd
(
cmd
,
1
,
status
,
NULL
,
0
,
0
);
spin_up_retry
=
1
;
goto
try_read_again
;
if
(
0
<=
seek_and_read_N_blocks
(
params
,
read_size
,
status
,
sony_buffer
,
(
read_size
*
2048
)))
break
;
if
(
!
(
status
[
0
]
&
SONY535_STATUS1_NOT_SPINNING
)
||
spin_up_retry
)
{
printk
(
CDU535_MESSAGE_NAME
" Read error: 0x%.2x
\n
"
,
status
[
0
]);
sony_first_block
=
-
1
;
sony_last_block
=
-
1
;
end_request
(
0
);
return
;
}
printk
(
"Sony CDROM Read error: 0x%.2x
\n
"
,
status
[
0
]);
sony_first_block
=
-
1
;
sony_last_block
=
-
1
;
end_request
(
0
);
return
;
printk
(
CDU535_MESSAGE_NAME
" debug: calling spin up when reading data!
\n
"
)
;
cmd
[
0
]
=
SONY535_SPIN_UP
;
do_sony_cmd
(
cmd
,
1
,
status
,
NULL
,
0
,
0
);
spin_up_retry
=
1
;
}
}
/*
...
...
@@ -866,7 +941,7 @@ do_cdu535_request(void)
static
void
sony_get_toc
(
void
)
{
unsigned
char
status
[
2
];
Byte
status
[
2
];
if
(
!
sony_toc_read
)
{
/* do not call check_drive_status() from here since it can call this routine */
if
(
request_toc_data
(
status
,
sony_toc
)
<
0
)
...
...
@@ -884,8 +959,8 @@ sony_get_toc(void)
static
int
find_track
(
int
track
)
{
int
i
;
int
num_tracks
;
int
i
;
int
num_tracks
;
num_tracks
=
bcd_to_int
(
sony_toc
->
last_track_num
)
-
...
...
@@ -905,16 +980,17 @@ find_track(int track)
static
int
read_subcode
(
void
)
{
Byte
cmd
=
SONY535_REQUEST_SUB_Q_DATA
,
status
[
2
];
int
dsc_status
;
Byte
cmd
=
SONY535_REQUEST_SUB_Q_DATA
;
Byte
status
[
2
];
int
dsc_status
;
if
(
check_drive_status
()
!=
0
)
return
-
EIO
;
if
((
dsc_status
=
do_sony_cmd
(
&
cmd
,
1
,
status
,
(
Byte
*
)
last_sony_subcode
,
sizeof
(
struct
s535_sony_subcode
),
1
))
!=
0
)
{
printk
(
"Sony CDROM error 0x%.2x, %d (read_subcode)
\n
"
,
status
[
0
]
,
dsc_status
);
sizeof
(
struct
s535_sony_subcode
),
1
))
!=
0
)
{
printk
(
CDU535_MESSAGE_NAME
" error 0x%.2x, %d (read_subcode)
\n
"
,
status
[
0
],
dsc_status
);
return
-
EIO
;
}
return
0
;
...
...
@@ -942,9 +1018,9 @@ sony_get_subchnl_info(long arg)
if
(
!
sony_toc_read
)
{
return
-
EIO
;
}
verify_area
(
VERIFY_WRITE
/* and read */
,
(
char
*
)
arg
,
sizeof
(
schi
)
);
verify_area
(
VERIFY_WRITE
/* and read */
,
(
char
*
)
arg
,
sizeof
schi
);
memcpy_fromfs
(
&
schi
,
(
char
*
)
arg
,
sizeof
(
schi
)
);
memcpy_fromfs
(
&
schi
,
(
char
*
)
arg
,
sizeof
schi
);
switch
(
sony_audio_status
)
{
case
CDROM_AUDIO_PLAY
:
...
...
@@ -959,7 +1035,7 @@ sony_get_subchnl_info(long arg)
case
CDROM_AUDIO_NO_STATUS
:
schi
.
cdsc_audiostatus
=
sony_audio_status
;
memcpy_tofs
((
char
*
)
arg
,
&
schi
,
sizeof
(
schi
)
);
memcpy_tofs
((
char
*
)
arg
,
&
schi
,
sizeof
schi
);
return
0
;
break
;
...
...
@@ -986,7 +1062,7 @@ sony_get_subchnl_info(long arg)
schi
.
cdsc_absaddr
.
lba
=
msf_to_log
(
last_sony_subcode
->
abs_msf
);
schi
.
cdsc_reladdr
.
lba
=
msf_to_log
(
last_sony_subcode
->
rel_msf
);
}
memcpy_tofs
((
char
*
)
arg
,
&
schi
,
sizeof
(
schi
)
);
memcpy_tofs
((
char
*
)
arg
,
&
schi
,
sizeof
schi
);
return
0
;
}
...
...
@@ -1001,9 +1077,9 @@ cdu_ioctl(struct inode *inode,
unsigned
long
arg
)
{
unsigned
int
dev
;
unsigned
char
status
[
2
];
unsigned
char
cmd_buff
[
10
],
params
[
10
];
int
i
,
dsc_status
;
Byte
status
[
2
];
Byte
cmd_buff
[
10
],
params
[
10
];
int
i
,
dsc_status
;
if
(
!
inode
)
{
...
...
@@ -1019,7 +1095,8 @@ cdu_ioctl(struct inode *inode,
switch
(
cmd
)
{
case
CDROMSTART
:
/* Spin up the drive */
if
(
spin_up_drive
(
status
)
<
0
)
{
printk
(
"Sony CDROM error 0x%.2x (CDROMSTART)
\n
"
,
status
[
0
]);
printk
(
CDU535_MESSAGE_NAME
" error 0x%.2x (CDROMSTART)
\n
"
,
status
[
0
]);
return
-
EIO
;
}
return
0
;
...
...
@@ -1038,7 +1115,8 @@ cdu_ioctl(struct inode *inode,
dsc_status
=
do_sony_cmd
(
cmd_buff
,
1
,
status
,
NULL
,
0
,
0
);
if
(((
dsc_status
<
0
)
&&
(
dsc_status
!=
BAD_STATUS
))
||
((
status
[
0
]
&
~
(
SONY535_STATUS1_NOT_SPINNING
))
!=
0
))
{
printk
(
"Sony CDROM error 0x%.2x (CDROMSTOP)
\n
"
,
status
[
0
]);
printk
(
CDU535_MESSAGE_NAME
" error 0x%.2x (CDROMSTOP)
\n
"
,
status
[
0
]);
return
-
EIO
;
}
return
0
;
...
...
@@ -1047,7 +1125,8 @@ cdu_ioctl(struct inode *inode,
case
CDROMPAUSE
:
/* Pause the drive */
cmd_buff
[
0
]
=
SONY535_HOLD
;
/* CDU-31 driver uses AUDIO_STOP, not pause */
if
(
do_sony_cmd
(
cmd_buff
,
1
,
status
,
NULL
,
0
,
0
)
!=
0
)
{
printk
(
"Sony CDROM error 0x%.2x (CDROMPAUSE)
\n
"
,
status
[
0
]);
printk
(
CDU535_MESSAGE_NAME
" error 0x%.2x (CDROMPAUSE)
\n
"
,
status
[
0
]);
return
-
EIO
;
}
/* Get the current position and save it for resuming */
...
...
@@ -1082,7 +1161,8 @@ cdu_ioctl(struct inode *inode,
cmd_buff
[
9
]
=
final_pos_msf
[
2
];
if
((
do_sony_cmd
(
cmd_buff
,
5
,
status
,
NULL
,
0
,
0
)
!=
0
)
||
(
do_sony_cmd
(
cmd_buff
+
5
,
5
,
status
,
NULL
,
0
,
0
)
!=
0
))
{
printk
(
"Sony CDROM error 0x%.2x (CDROMRESUME)
\n
"
,
status
[
0
]);
printk
(
CDU535_MESSAGE_NAME
" error 0x%.2x (CDROMRESUME)
\n
"
,
status
[
0
]);
return
-
EIO
;
}
sony_audio_status
=
CDROM_AUDIO_PLAY
;
...
...
@@ -1108,7 +1188,8 @@ cdu_ioctl(struct inode *inode,
/* cmd_buff[7-9] are filled in for loop above */
if
((
do_sony_cmd
(
cmd_buff
,
5
,
status
,
NULL
,
0
,
0
)
!=
0
)
||
(
do_sony_cmd
(
cmd_buff
+
5
,
5
,
status
,
NULL
,
0
,
0
)
!=
0
))
{
printk
(
"Sony CDROM error 0x%.2x (CDROMPLAYMSF)
\n
"
,
status
[
0
]);
printk
(
CDU535_MESSAGE_NAME
" error 0x%.2x (CDROMPLAYMSF)
\n
"
,
status
[
0
]);
return
-
EIO
;
}
/* Save the final position for pauses and resumes */
...
...
@@ -1128,10 +1209,10 @@ cdu_ioctl(struct inode *inode,
if
(
!
sony_toc_read
)
return
-
EIO
;
hdr
=
(
struct
cdrom_tochdr
*
)
arg
;
verify_area
(
VERIFY_WRITE
,
hdr
,
sizeof
(
*
hdr
)
);
verify_area
(
VERIFY_WRITE
,
hdr
,
sizeof
*
hdr
);
loc_hdr
.
cdth_trk0
=
bcd_to_int
(
sony_toc
->
first_track_num
);
loc_hdr
.
cdth_trk1
=
bcd_to_int
(
sony_toc
->
last_track_num
);
memcpy_tofs
(
hdr
,
&
loc_hdr
,
sizeof
(
*
hdr
)
);
memcpy_tofs
(
hdr
,
&
loc_hdr
,
sizeof
*
hdr
);
}
return
0
;
break
;
...
...
@@ -1140,17 +1221,17 @@ cdu_ioctl(struct inode *inode,
{
struct
cdrom_tocentry
*
entry
;
struct
cdrom_tocentry
loc_entry
;
int
track_idx
;
unsigned
char
*
msf_val
=
NULL
;
int
track_idx
;
Byte
*
msf_val
=
NULL
;
sony_get_toc
();
if
(
!
sony_toc_read
)
{
return
-
EIO
;
}
entry
=
(
struct
cdrom_tocentry
*
)
arg
;
verify_area
(
VERIFY_WRITE
/* and read */
,
entry
,
sizeof
(
*
entry
)
);
verify_area
(
VERIFY_WRITE
/* and read */
,
entry
,
sizeof
*
entry
);
memcpy_fromfs
(
&
loc_entry
,
entry
,
sizeof
(
loc_entry
)
);
memcpy_fromfs
(
&
loc_entry
,
entry
,
sizeof
loc_entry
);
/* Lead out is handled separately since it is special. */
if
(
loc_entry
.
cdte_track
==
CDROM_LEADOUT
)
{
...
...
@@ -1174,7 +1255,7 @@ cdu_ioctl(struct inode *inode,
loc_entry
.
cdte_addr
.
msf
.
second
=
bcd_to_int
(
*
(
msf_val
+
1
));
loc_entry
.
cdte_addr
.
msf
.
frame
=
bcd_to_int
(
*
(
msf_val
+
2
));
}
memcpy_tofs
(
entry
,
&
loc_entry
,
sizeof
(
*
entry
)
);
memcpy_tofs
(
entry
,
&
loc_entry
,
sizeof
*
entry
);
}
return
0
;
break
;
...
...
@@ -1182,14 +1263,14 @@ cdu_ioctl(struct inode *inode,
case
CDROMPLAYTRKIND
:
/* Play a track. This currently ignores index. */
{
struct
cdrom_ti
ti
;
int
track_idx
;
int
track_idx
;
sony_get_toc
();
if
(
!
sony_toc_read
)
return
-
EIO
;
verify_area
(
VERIFY_READ
,
(
char
*
)
arg
,
sizeof
(
ti
)
);
verify_area
(
VERIFY_READ
,
(
char
*
)
arg
,
sizeof
ti
);
memcpy_fromfs
(
&
ti
,
(
char
*
)
arg
,
sizeof
(
ti
)
);
memcpy_fromfs
(
&
ti
,
(
char
*
)
arg
,
sizeof
ti
);
if
((
ti
.
cdti_trk0
<
sony_toc
->
first_track_num
)
||
(
sony_toc
->
last_track_num
<
ti
.
cdti_trk0
)
||
(
ti
.
cdti_trk1
<
ti
.
cdti_trk0
))
{
...
...
@@ -1234,9 +1315,11 @@ cdu_ioctl(struct inode *inode,
cmd_buff
[
9
]
=
params
[
6
];
if
((
do_sony_cmd
(
cmd_buff
,
5
,
status
,
NULL
,
0
,
0
)
!=
0
)
||
(
do_sony_cmd
(
cmd_buff
+
5
,
5
,
status
,
NULL
,
0
,
0
)
!=
0
))
{
printk
(
"Params: %x %x %x %x %x %x %x
\n
"
,
params
[
0
],
params
[
1
],
params
[
2
],
params
[
3
],
params
[
4
],
params
[
5
],
params
[
6
]);
printk
(
"Sony CDROM error 0x%.2x (CDROMPLAYTRKIND)
\n
"
,
status
[
0
]);
printk
(
CDU535_MESSAGE_NAME
" error 0x%.2x (CDROMPLAYTRKIND)
\n
"
,
status
[
0
]);
printk
(
"... Params: %x %x %x %x %x %x %x
\n
"
,
params
[
0
],
params
[
1
],
params
[
2
],
params
[
3
],
params
[
4
],
params
[
5
],
params
[
6
]);
return
-
EIO
;
}
/* Save the final position for pauses and resumes */
...
...
@@ -1254,14 +1337,15 @@ cdu_ioctl(struct inode *inode,
{
struct
cdrom_volctrl
volctrl
;
verify_area
(
VERIFY_READ
,
(
char
*
)
arg
,
sizeof
(
volctrl
)
);
verify_area
(
VERIFY_READ
,
(
char
*
)
arg
,
sizeof
volctrl
);
memcpy_fromfs
(
&
volctrl
,
(
char
*
)
arg
,
sizeof
(
volctrl
)
);
memcpy_fromfs
(
&
volctrl
,
(
char
*
)
arg
,
sizeof
volctrl
);
cmd_buff
[
0
]
=
SONY535_SET_VOLUME
;
cmd_buff
[
1
]
=
volctrl
.
channel0
;
cmd_buff
[
2
]
=
volctrl
.
channel1
;
if
(
do_sony_cmd
(
cmd_buff
,
3
,
status
,
NULL
,
0
,
0
)
!=
0
)
{
printk
(
"Sony CDROM error 0x%.2x (CDROMVOLCTRL)
\n
"
,
status
[
0
]);
printk
(
CDU535_MESSAGE_NAME
" error 0x%.2x (CDROMVOLCTRL)
\n
"
,
status
[
0
]);
return
-
EIO
;
}
}
...
...
@@ -1276,7 +1360,8 @@ cdu_ioctl(struct inode *inode,
sony_audio_status
=
CDROM_AUDIO_INVALID
;
cmd_buff
[
0
]
=
SONY535_EJECT_CADDY
;
if
(
do_sony_cmd
(
cmd_buff
,
1
,
status
,
NULL
,
0
,
0
)
!=
0
)
{
printk
(
"Sony CDROM error 0x%.2x (CDROMEJECT)
\n
"
,
status
[
0
]);
printk
(
CDU535_MESSAGE_NAME
" error 0x%.2x (CDROMEJECT)
\n
"
,
status
[
0
]);
return
-
EIO
;
}
return
0
;
...
...
@@ -1296,7 +1381,7 @@ static int
cdu_open
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
unsigned
char
status
[
2
],
cmd_buff
[
2
];
Byte
status
[
2
],
cmd_buff
[
2
];
if
(
sony_inuse
)
...
...
@@ -1307,7 +1392,8 @@ cdu_open(struct inode *inode,
MOD_INC_USE_COUNT
;
if
(
spin_up_drive
(
status
)
!=
0
)
{
printk
(
"Sony CDROM error 0x%.2x (cdu_open, spin up)
\n
"
,
status
[
0
]);
printk
(
CDU535_MESSAGE_NAME
" error 0x%.2x (cdu_open, spin up)
\n
"
,
status
[
0
]);
sony_inuse
=
0
;
MOD_DEC_USE_COUNT
;
return
-
EIO
;
...
...
@@ -1343,7 +1429,7 @@ static void
cdu_release
(
struct
inode
*
inode
,
struct
file
*
filp
)
{
unsigned
char
status
[
2
],
cmd_no
;
Byte
status
[
2
],
cmd_no
;
sony_inuse
=
0
;
MOD_DEC_USE_COUNT
;
...
...
@@ -1392,28 +1478,44 @@ static struct file_operations cdu_fops =
unsigned
long
sony535_init
(
unsigned
long
mem_start
,
unsigned
long
mem_end
)
#else
int
int
init_module
(
void
)
#endif
{
struct
s535_sony_drive_config
drive_config
;
unsigned
char
cmd_buff
[
3
],
ret_buff
[
2
];
unsigned
char
status
[
2
];
int
retry_count
;
Byte
cmd_buff
[
3
];
Byte
ret_buff
[
2
];
Byte
status
[
2
];
int
retry_count
;
int
tmp_irq
;
#ifdef MODULE
int
i
;
int
i
;
#endif
/* Setting the base I/O address to 0xffff will disable it. */
if
(
sony535_cd_base_io
==
0xffff
)
goto
bail
;
/* Set up all the register locations */
result_reg
=
sony_cd_base_io
;
command_reg
=
sony_cd_base_io
;
data_reg
=
sony_cd_base_io
+
1
;
read_status_reg
=
sony_cd_base_io
+
2
;
select_unit_reg
=
sony_cd_base_io
+
3
;
printk
(
"sonycd535: probing base address %03X
\n
"
,
sony_cd_base_io
);
if
(
check_region
(
sony_cd_base_io
,
4
))
{
printk
(
"sonycd535: my base address is not free!
\n
"
);
result_reg
=
sony535_cd_base_io
;
command_reg
=
sony535_cd_base_io
;
data_reg
=
sony535_cd_base_io
+
1
;
read_status_reg
=
sony535_cd_base_io
+
2
;
select_unit_reg
=
sony535_cd_base_io
+
3
;
#ifndef USE_IRQ
sony535_irq_used
=
0
;
/* polling only until this is ready... */
#endif
/* we need to poll until things get initialized */
tmp_irq
=
sony535_irq_used
;
sony535_irq_used
=
0
;
#if DEBUG > 0
printk
(
CDU535_MESSAGE_NAME
": probing base address %03X
\n
"
,
sony535_cd_base_io
);
#endif
if
(
check_region
(
sony535_cd_base_io
,
4
))
{
printk
(
CDU535_MESSAGE_NAME
": my base address is not free!
\n
"
);
#ifndef MODULE
return
mem_start
;
#else
...
...
@@ -1433,19 +1535,46 @@ init_module(void)
select_unit
(
0
);
if
(
inb
(
result_reg
)
!=
0xff
)
break
;
sony_sleep
();
/* about 1-2 ms on my machine */
sony_sleep
();
}
if
((
jiffies
<
retry_count
)
&&
(
check_drive_status
()
!=
TIME_OUT
))
{
/* CD-ROM drive responded -- get the drive configuration */
cmd_buff
[
0
]
=
SONY535_INQUIRY
;
if
(
do_sony_cmd
(
cmd_buff
,
1
,
status
,
(
Byte
*
)
&
drive_config
,
28
,
1
)
==
0
)
{
/* was able to get the configuration, set drive mode as rest of init */
if
(
do_sony_cmd
(
cmd_buff
,
1
,
status
,
(
Byte
*
)
&
drive_config
,
28
,
1
)
==
0
)
{
/* was able to get the configuration,
* set drive mode as rest of init
*/
#if DEBUG > 0
/* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */
if
(
(
status
[
0
]
&
0x7f
)
!=
0
&&
(
status
[
0
]
&
0x7f
)
!=
0x50
)
printk
(
"Inquiry command returned status = 0x%x
\n
"
,
status
[
0
]);
printk
(
CDU535_MESSAGE_NAME
"Inquiry command returned status = 0x%x
\n
"
,
status
[
0
]);
#endif
/* now ready to use interrupts, if available */
sony535_irq_used
=
tmp_irq
;
#ifndef MODULE
/* This code is not in MODULEs by default, since the autoirq stuff might
* not be in the module-accessable symbol table.
*/
/* A negative sony535_irq_used will attempt an autoirq. */
if
(
sony535_irq_used
<
0
)
{
autoirq_setup
(
0
);
enable_interrupts
();
outb
(
0
,
read_status_reg
);
/* does a reset? */
sony535_irq_used
=
autoirq_report
(
10
);
disable_interrupts
();
}
#endif
if
(
sony535_irq_used
>
0
)
{
if
(
request_irq
(
sony535_irq_used
,
cdu535_interrupt
,
SA_INTERRUPT
,
CDU535_HANDLE
))
{
printk
(
"Unable to grab IRQ%d for the "
CDU535_MESSAGE_NAME
" driver; polling instead.
\n
"
,
sony535_irq_used
);
sony535_irq_used
=
0
;
}
}
cmd_buff
[
0
]
=
SONY535_SET_DRIVE_MODE
;
cmd_buff
[
1
]
=
0x0
;
/* default audio */
if
(
do_sony_cmd
(
cmd_buff
,
2
,
status
,
ret_buff
,
1
,
1
)
==
0
)
{
...
...
@@ -1453,11 +1582,14 @@ init_module(void)
sony_buffer_size
=
SONY535_BUFFER_SIZE
;
sony_buffer_sectors
=
sony_buffer_size
/
2048
;
printk
(
"Sony
I/F CDROM : %8.8s %16.16s %4.4s"
,
printk
(
CDU535_MESSAGE_NAME
"
I/F CDROM : %8.8s %16.16s %4.4s"
,
drive_config
.
vendor_id
,
drive_config
.
product_id
,
drive_config
.
product_rev_level
);
printk
(
" using %d byte buffer
\n
"
,
sony_buffer_size
);
printk
(
" base address %03X, "
,
sony535_cd_base_io
);
if
(
tmp_irq
>
0
)
printk
(
"IRQ%d, "
,
tmp_irq
);
printk
(
"using %d byte buffer
\n
"
,
sony_buffer_size
);
if
(
register_blkdev
(
MAJOR_NR
,
CDU535_HANDLE
,
&
cdu_fops
))
{
printk
(
"Unable to get major %d for %s
\n
"
,
...
...
@@ -1473,21 +1605,21 @@ init_module(void)
#ifndef MODULE
sony_toc
=
(
struct
s535_sony_toc
*
)
mem_start
;
mem_start
+=
sizeof
(
*
sony_toc
)
;
mem_start
+=
sizeof
*
sony_toc
;
last_sony_subcode
=
(
struct
s535_sony_subcode
*
)
mem_start
;
mem_start
+=
sizeof
(
*
last_sony_subcode
)
;
sony_buffer
=
(
unsigned
char
*
)
mem_start
;
mem_start
+=
sizeof
*
last_sony_subcode
;
sony_buffer
=
(
Byte
*
)
mem_start
;
mem_start
+=
sony_buffer_size
;
#else
/* MODULE */
sony_toc
=
(
struct
s535_sony_toc
*
)
kmalloc
(
sizeof
(
*
sony_toc
)
,
GFP_KERNEL
);
kmalloc
(
sizeof
*
sony_toc
,
GFP_KERNEL
);
last_sony_subcode
=
(
struct
s535_sony_subcode
*
)
kmalloc
(
sizeof
(
*
last_sony_subcode
)
,
GFP_KERNEL
);
sony_buffer
=
(
unsigned
char
**
)
kmalloc
(
sizeof
*
last_sony_subcode
,
GFP_KERNEL
);
sony_buffer
=
(
Byte
**
)
kmalloc
(
4
*
sony_buffer_sectors
,
GFP_KERNEL
);
for
(
i
=
0
;
i
<
sony_buffer_sectors
;
i
++
)
sony_buffer
[
i
]
=
(
unsigned
char
*
)
kmalloc
(
2048
,
GFP_KERNEL
);
sony_buffer
[
i
]
=
(
Byte
*
)
kmalloc
(
2048
,
GFP_KERNEL
);
#endif
/* MODULE */
initialized
=
1
;
}
...
...
@@ -1500,8 +1632,9 @@ init_module(void)
return
-
EIO
;
#endif
}
else
{
request_region
(
sony_cd_base_io
,
4
,
CDU535_HANDLE
);
request_region
(
sony
535
_cd_base_io
,
4
,
CDU535_HANDLE
);
}
bail:
#ifndef MODULE
return
mem_start
;
#else
...
...
@@ -1511,7 +1644,7 @@ init_module(void)
#ifndef MODULE
/*
* accept "kernel command line" parameters
* accept "kernel command line" parameters
* (added by emoenke@gwdg.de)
*
* use: tell LILO:
...
...
@@ -1522,33 +1655,35 @@ init_module(void)
void
sonycd535_setup
(
char
*
strings
,
int
*
ints
)
{
/* if IRQ change and default io base desired,
* then call with io base of 0
*/
if
(
ints
[
0
]
>
0
)
sony_cd_base_io
=
ints
[
1
];
#if 0 /* placeholder for future use */
if
(
ints
[
0
]
!=
0
)
sony535_cd_base_io
=
ints
[
1
];
if
(
ints
[
0
]
>
1
)
irq_used = ints[2];
#endif
sony535_irq_used
=
ints
[
2
];
if
((
strings
!=
NULL
)
&&
(
*
strings
!=
'\0'
))
printk
(
"%s: Warning: Unknown interface type: %s
\n
"
,
strings
,
CDU535_MESSAGE_NAME
);
printk
(
CDU535_MESSAGE_NAME
": Warning: Unknown interface type: %s
\n
"
,
strings
);
}
#else
/* MODULE */
void
void
cleanup_module
(
void
)
{
int
i
;
if
(
MOD_IN_USE
)
{
printk
(
"Sony 535
module in use, cannot remove
\n
"
);
printk
(
CDU535_HANDLE
"
module in use, cannot remove
\n
"
);
return
;
}
release_region
(
sony_cd_base_io
,
4
);
kfree_s
(
sony_toc
,
sizeof
(
*
sony_toc
));
kfree_s
(
last_sony_subcode
,
sizeof
(
*
last_sony_subcode
));
release_region
(
sony535_cd_base_io
,
4
);
for
(
i
=
0
;
i
<
sony_buffer_sectors
;
i
++
)
kfree_s
(
sony_buffer
[
i
],
2048
);
kfree_s
(
sony_buffer
,
4
*
sony_buffer_sectors
);
kfree_s
(
last_sony_subcode
,
sizeof
*
last_sony_subcode
);
kfree_s
(
sony_toc
,
sizeof
*
sony_toc
);
if
(
unregister_blkdev
(
MAJOR_NR
,
CDU535_HANDLE
)
==
-
EINVAL
)
printk
(
"Uh oh, couldn't unregister "
CDU535_HANDLE
"
\n
"
);
else
...
...
drivers/char/ChangeLog
View file @
5d278332
Sat Feb 18 12:13:51 1995 Theodore Y. Ts'o (tytso@rt-11)
* tty_io.c (disassociate_ctty, tty_open, tty_ioctl): Clear
current->tty_old_pgrp field when a session leader
acquires a controlling tty, and after a session leader
has disassociated from a controlling tty.
Fri Feb 17 09:34:09 1995 Theodore Y. Ts'o (tytso@rt-11)
* serial.c (rs_interrupt_single, rs_interrupt, rs_interrupt_multi):
Change the the number of passes made from 64 to be 256,
configurable with the #define RS_ISR_PASS_LIMIT.
* serial.c (rs_init, set_serial_info, get_serial_info, rs_close):
Remove support for closing_wait2. Instead, set
tty->closing and rely on the line dispcline to prevent
echo wars.
* n_tty.c (n_tty_receive_char): IEXTEN does not need to be
enabled in order for IXANY to be active.
If tty->closing is set, then only process XON and XOFF
characters.
Sun Feb 12 23:57:48 1995 Theodore Y. Ts'o (tytso@rt-11)
* serial.c (rs_timer): Change the interrupt poll time from 60
seconds to 10 seconds, configurable with the #define
RS_STROBE_TIME.
* serial.c (rs_interrupt_multi, startup, shutdown, rs_ioctl,
set_multiport_struct, get_multiport_struct): Add
provisions for a new type of interrutp service routine,
which better supports multiple serial ports on a single
IRQ.
Sun Feb 5 19:35:11 1995 Theodore Y. Ts'o (tytso@rt-11)
* tty_ioctl.c (n_tty_ioctl, set_termios, tty_wait_until_sent):
* serial.c (rs_ioctl, rs_close):
* cyclades.c (cy_ioctl, cy_close):
* n_tty.c (n_tty_close): Rename wait_until_sent to
tty_wait_until_sent, so that it's a better name to export
in ksyms.c.
Sat Feb 4 23:36:20 1995 Theodore Y. Ts'o (tytso@rt-11)
* serial.c (rs_close): Added missing check for closing_wait2 being
ASYNC_CLOSING_WAIT_NONE.
Thu Jan 26 09:02:49 1995 Theodore Y. Ts'o (tytso@rt-11)
* serial.c (rs_init, set_serial_info, get_serial_info,
rs_close): Support close_wait in the serial driver.
This is helpful for slow devices (like serial
plotters) so that their outputs don't get flushed upon
device close. This has to be configurable because
normally we don't want ports to be hung up for long
periods of time during a close when they are not
connected to a device, or the device is powered off.
The default is to wait 30 seconds; in the case of a
very slow device, the close_wait timeout should be
lengthed. If it is set to 0, the kernel will wait
forever for all of the data to be transmitted.
Thu Jan 17 01:17:20 1995 Theodore Y. Ts'o (tytso@rt-11)
* serial.c (startup, change_speed, rs_init): Add support to detect
the StarTech 16650 chip. Treat it as a 16450 for now,
because of its FIFO bugs.
Thu Jan 5 21:21:57 1995 <dhinds@allegro.stanford.edu>
* serial.c: (receive_char): Added counter to prevent infinite loop
...
...
drivers/char/n_tty.c
View file @
5d278332
...
...
@@ -345,7 +345,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
return
;
}
if
(
tty
->
stopped
&&
I_IXON
(
tty
)
&&
I_IXANY
(
tty
)
&&
L_IEXTEN
(
tty
)
)
{
if
(
tty
->
stopped
&&
I_IXON
(
tty
)
&&
I_IXANY
(
tty
))
{
start_tty
(
tty
);
return
;
}
...
...
@@ -355,6 +355,16 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
if
(
I_IUCLC
(
tty
)
&&
L_IEXTEN
(
tty
))
c
=
tolower
(
c
);
if
(
tty
->
closing
)
{
if
(
I_IXON
(
tty
))
{
if
(
c
==
START_CHAR
(
tty
))
start_tty
(
tty
);
else
if
(
c
==
STOP_CHAR
(
tty
))
stop_tty
(
tty
);
}
return
;
}
/*
* If the previous character was LNEXT, or we know that this
* character is not one of the characters that we'll have to
...
...
@@ -690,6 +700,7 @@ static int n_tty_open(struct tty_struct *tty)
memset
(
tty
->
read_flags
,
0
,
sizeof
(
tty
->
read_flags
));
n_tty_set_termios
(
tty
,
0
);
tty
->
minimum_to_wake
=
1
;
tty
->
closing
=
0
;
return
0
;
}
...
...
drivers/char/selection.c
View file @
5d278332
...
...
@@ -3,10 +3,10 @@
*
* This module exports the functions:
*
* 'int set_selection(const
int
arg)'
* 'int set_selection(const
unsigned long
arg)'
* 'void clear_selection(void)'
* 'int paste_selection(struct tty_struct *tty)'
* 'int sel_loadlut(const
int
arg)'
* 'int sel_loadlut(const
unsigned long
arg)'
*
* Now that /dev/vcs exists, most of this can disappear again.
*/
...
...
@@ -15,6 +15,9 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/malloc.h>
#include <asm/segment.h>
#include "vt_kern.h"
#include "consolemap.h"
#include "selection.h"
...
...
@@ -82,7 +85,7 @@ static inline int inword(const unsigned char c) {
}
/* set inwordLut contents. Invoked by ioctl(). */
int
sel_loadlut
(
const
int
arg
)
int
sel_loadlut
(
const
unsigned
long
arg
)
{
int
i
=
verify_area
(
VERIFY_READ
,
(
char
*
)
arg
,
36
);
if
(
i
)
...
...
@@ -107,7 +110,7 @@ static inline unsigned short limit(const unsigned short v, const unsigned short
}
/* set the current selection. Invoked by ioctl(). */
int
set_selection
(
const
int
arg
,
struct
tty_struct
*
tty
)
int
set_selection
(
const
unsigned
long
arg
,
struct
tty_struct
*
tty
)
{
int
sel_mode
,
new_sel_start
,
new_sel_end
,
spc
;
char
*
bp
,
*
obp
;
...
...
drivers/char/selection.h
View file @
5d278332
...
...
@@ -6,9 +6,9 @@
extern
int
sel_cons
;
extern
void
clear_selection
(
void
);
extern
int
set_selection
(
const
int
arg
,
struct
tty_struct
*
tty
);
extern
int
set_selection
(
const
unsigned
long
arg
,
struct
tty_struct
*
tty
);
extern
int
paste_selection
(
struct
tty_struct
*
tty
);
extern
int
sel_loadlut
(
const
int
arg
);
extern
int
sel_loadlut
(
const
unsigned
long
arg
);
extern
int
mouse_reporting
(
void
);
extern
void
mouse_report
(
struct
tty_struct
*
tty
,
int
butt
,
int
mrx
,
int
mry
);
...
...
@@ -33,7 +33,9 @@ extern void putconsxy(int currcons, char *p);
/* how to access screen memory */
#ifdef __alpha__
#include <asm/io.h>
static
inline
void
scr_writew
(
unsigned
short
val
,
unsigned
short
*
addr
)
{
if
((
long
)
addr
<
0
)
...
...
drivers/char/serial.c
View file @
5d278332
...
...
@@ -67,12 +67,14 @@ static int serial_refcount;
#define SERIAL_PARANOIA_CHECK
#define CONFIG_SERIAL_NOPAUSE_IO
#define SERIAL_DO_RESTART
#define CONFIG_SERIAL_NEW_ISR
#undef SERIAL_DEBUG_INTR
#undef SERIAL_DEBUG_OPEN
#undef SERIAL_DEBUG_FLOW
#define RS_STROBE_TIME 10
#define RS_ISR_PASS_LIMIT 256
#define _INLINE_ inline
/*
...
...
@@ -81,6 +83,7 @@ static int serial_refcount;
*/
static
struct
async_struct
*
IRQ_ports
[
16
];
static
struct
rs_multiport_struct
rs_multiport
[
16
];
static
int
IRQ_timeout
[
16
];
static
volatile
int
rs_irq_triggered
;
static
volatile
int
rs_triggered
;
...
...
@@ -420,9 +423,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
if
((
info
->
xmit_cnt
<=
0
)
||
info
->
tty
->
stopped
||
info
->
tty
->
hw_stopped
)
{
info
->
IER
&=
~
UART_IER_THRI
;
#ifdef CONFIG_SERIAL_NEW_ISR
serial_out
(
info
,
UART_IER
,
info
->
IER
);
#endif
return
;
}
...
...
@@ -445,9 +446,7 @@ static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
if
(
info
->
xmit_cnt
<=
0
)
{
info
->
IER
&=
~
UART_IER_THRI
;
#ifdef CONFIG_SERIAL_NEW_ISR
serial_out
(
info
,
UART_IER
,
info
->
IER
);
#endif
}
}
...
...
@@ -480,9 +479,7 @@ static _INLINE_ void check_modem_status(struct async_struct *info)
#endif
info
->
tty
->
hw_stopped
=
0
;
info
->
IER
|=
UART_IER_THRI
;
#ifdef CONFIG_SERIAL_NEW_ISR
serial_out
(
info
,
UART_IER
,
info
->
IER
);
#endif
rs_sched_event
(
info
,
RS_EVENT_WRITE_WAKEUP
);
return
;
}
...
...
@@ -493,15 +490,12 @@ static _INLINE_ void check_modem_status(struct async_struct *info)
#endif
info
->
tty
->
hw_stopped
=
1
;
info
->
IER
&=
~
UART_IER_THRI
;
#ifdef CONFIG_SERIAL_NEW_ISR
serial_out
(
info
,
UART_IER
,
info
->
IER
);
#endif
}
}
}
}
#ifdef CONFIG_SERIAL_NEW_ISR
/*
* This is the serial driver's generic interrupt routine
*/
...
...
@@ -511,6 +505,8 @@ static void rs_interrupt(int irq, struct pt_regs * regs)
struct
async_struct
*
info
;
int
pass_counter
=
0
;
struct
async_struct
*
end_mark
=
0
;
int
first_multi
=
0
;
struct
rs_multiport_struct
*
multi
;
#ifdef SERIAL_DEBUG_INTR
printk
(
"rs_interrupt(%d)..."
,
irq
);
...
...
@@ -520,6 +516,10 @@ static void rs_interrupt(int irq, struct pt_regs * regs)
if
(
!
info
)
return
;
multi
=
&
rs_multiport
[
irq
];
if
(
multi
->
port_monitor
)
first_multi
=
inb
(
multi
->
port_monitor
);
do
{
if
(
!
info
->
tty
||
(
serial_in
(
info
,
UART_IIR
)
&
UART_IIR_NO_INT
))
{
...
...
@@ -545,7 +545,7 @@ static void rs_interrupt(int irq, struct pt_regs * regs)
info
=
info
->
next_port
;
if
(
!
info
)
{
info
=
IRQ_ports
[
irq
];
if
(
pass_counter
++
>
64
)
{
if
(
pass_counter
++
>
RS_ISR_PASS_LIMIT
)
{
#if 0
printk("rs loop break\n");
#endif
...
...
@@ -554,6 +554,9 @@ static void rs_interrupt(int irq, struct pt_regs * regs)
continue
;
}
}
while
(
end_mark
!=
info
);
if
(
multi
->
port_monitor
)
printk
(
"rs port monitor (normal) irq %d: 0x%x, 0x%x
\n
"
,
info
->
irq
,
first_multi
,
inb
(
multi
->
port_monitor
));
#ifdef SERIAL_DEBUG_INTR
printk
(
"end.
\n
"
);
#endif
...
...
@@ -566,7 +569,9 @@ static void rs_interrupt_single(int irq, struct pt_regs * regs)
{
int
status
;
int
pass_counter
=
0
;
int
first_multi
=
0
;
struct
async_struct
*
info
;
struct
rs_multiport_struct
*
multi
;
#ifdef SERIAL_DEBUG_INTR
printk
(
"rs_interrupt_single(%d)..."
,
irq
);
...
...
@@ -576,6 +581,10 @@ static void rs_interrupt_single(int irq, struct pt_regs * regs)
if
(
!
info
||
!
info
->
tty
)
return
;
multi
=
&
rs_multiport
[
irq
];
if
(
multi
->
port_monitor
)
first_multi
=
inb
(
multi
->
port_monitor
);
do
{
status
=
serial_inp
(
info
,
UART_LSR
)
&
info
->
read_status_mask
;
#ifdef SERIAL_DEBUG_INTR
...
...
@@ -586,7 +595,7 @@ static void rs_interrupt_single(int irq, struct pt_regs * regs)
check_modem_status
(
info
);
if
(
status
&
UART_LSR_THRE
)
transmit_chars
(
info
,
0
);
if
(
pass_counter
++
>
64
)
{
if
(
pass_counter
++
>
RS_ISR_PASS_LIMIT
)
{
#if 0
printk("rs_single loop break.\n");
#endif
...
...
@@ -594,102 +603,95 @@ static void rs_interrupt_single(int irq, struct pt_regs * regs)
}
}
while
(
!
(
serial_in
(
info
,
UART_IIR
)
&
UART_IIR_NO_INT
));
info
->
last_active
=
jiffies
;
if
(
multi
->
port_monitor
)
printk
(
"rs port monitor (single) irq %d: 0x%x, 0x%x
\n
"
,
info
->
irq
,
first_multi
,
inb
(
multi
->
port_monitor
));
#ifdef SERIAL_DEBUG_INTR
printk
(
"end.
\n
"
);
#endif
}
#else
/* CONFIG_SERIAL_NEW_ISR */
/*
* This is the serial driver's
generic interrupt routine
* This is the serial driver's
for multiport boards
*/
static
void
rs_interrupt
(
int
irq
,
struct
pt_regs
*
regs
)
static
void
rs_interrupt
_multi
(
int
irq
,
struct
pt_regs
*
regs
)
{
int
status
;
struct
async_struct
*
info
;
int
done
=
1
,
pass_counter
=
0
;
int
pass_counter
=
0
;
int
first_multi
=
0
;
struct
rs_multiport_struct
*
multi
;
#ifdef SERIAL_DEBUG_INTR
printk
(
"rs_interrupt(%d)..."
,
irq
);
printk
(
"rs_interrupt
_multi
(%d)..."
,
irq
);
#endif
info
=
IRQ_ports
[
irq
];
if
(
!
info
)
return
;
multi
=
&
rs_multiport
[
irq
];
if
(
!
multi
->
port1
)
{
/* Should never happen */
printk
(
"rs_interrupt_multi: NULL port1!
\n
"
);
return
;
}
if
(
multi
->
port_monitor
)
first_multi
=
inb
(
multi
->
port_monitor
);
while
(
1
)
{
if
(
!
info
->
tty
)
if
(
!
info
->
tty
||
(
serial_in
(
info
,
UART_IIR
)
&
UART_IIR_NO_INT
))
goto
next
;
serial_outp
(
info
,
UART_IER
,
0
);
info
->
last_active
=
jiffies
;
status
=
serial_inp
(
info
,
UART_LSR
)
&
info
->
read_status_mask
;
if
(
status
&
UART_LSR_DR
)
{
#ifdef SERIAL_DEBUG_INTR
printk
(
"status = %x..."
,
status
);
#endif
if
(
status
&
UART_LSR_DR
)
receive_chars
(
info
,
&
status
);
done
=
0
;
}
check_modem_status
(
info
);
if
(
status
&
UART_LSR_THRE
)
transmit_chars
(
info
,
&
done
);
transmit_chars
(
info
,
0
);
next:
info
=
info
->
next_port
;
if
(
!
info
)
{
info
=
IRQ_ports
[
irq
];
if
(
done
)
break
;
done
=
1
;
if
(
pass_counter
++
>
64
)
{
#if 0
printk("rs loop break\n");
info
=
info
->
next_port
;
if
(
info
)
continue
;
info
=
IRQ_ports
[
irq
];
if
(
pass_counter
++
>
RS_ISR_PASS_LIMIT
)
{
#if 1
printk
(
"rs_multi loop break
\n
"
);
#endif
break
;
/* Prevent infinite loops */
}
break
;
/* Prevent infinite loops */
}
}
/*
* Reset the IER registers; info is already set up from the
* above while loop.
*/
do
serial_outp
(
info
,
UART_IER
,
info
->
IER
)
;
while
((
info
=
info
->
next_port
)
!=
NULL
);
}
/*
* This is the serial driver's interrupt routine for a single port
*/
static
void
rs_interrupt_single
(
int
irq
,
struct
pt_regs
*
regs
)
{
int
status
;
struct
async_struct
*
info
;
if
(
multi
->
port_monitor
)
printk
(
"rs port monitor irq %d: 0x%x, 0x%x
\n
"
,
info
->
irq
,
first_multi
,
inb
(
multi
->
port_monitor
));
if
((
inb
(
multi
->
port1
)
&
multi
->
mask1
)
!=
multi
->
match1
)
continue
;
if
(
!
multi
->
port2
)
break
;
if
((
inb
(
multi
->
port2
)
&
multi
->
mask2
)
!=
multi
->
match2
)
continue
;
if
(
!
multi
->
port3
)
break
;
if
((
inb
(
multi
->
port3
)
&
multi
->
mask3
)
!=
multi
->
match3
)
continue
;
if
(
!
multi
->
port4
)
break
;
if
((
inb
(
multi
->
port4
)
&
multi
->
mask4
)
==
multi
->
match4
)
continue
;
break
;
}
#ifdef SERIAL_DEBUG_INTR
printk
(
"
rs_interrupt_single(%d)..."
,
irq
);
printk
(
"
end.
\n
"
);
#endif
info
=
IRQ_ports
[
irq
];
if
(
!
info
||
!
info
->
tty
)
return
;
serial_outp
(
info
,
UART_IER
,
0
);
status
=
serial_inp
(
info
,
UART_LSR
)
&
info
->
read_status_mask
;
if
(
status
&
UART_LSR_DR
)
receive_chars
(
info
,
&
status
);
check_modem_status
(
info
);
if
(
status
&
UART_LSR_THRE
)
transmit_chars
(
info
,
0
);
/*
* Reset the IER register
*/
serial_outp
(
info
,
UART_IER
,
info
->
IER
);
}
#endif
/* CONFIG_SERIAL_NEW_ISR */
/*
* -------------------------------------------------------------------
...
...
@@ -747,7 +749,7 @@ static void rs_timer(void)
struct
async_struct
*
info
;
unsigned
int
i
;
if
((
jiffies
-
last_strobe
)
>=
60
*
HZ
)
{
if
((
jiffies
-
last_strobe
)
>=
RS_STROBE_TIME
*
HZ
)
{
for
(
i
=
1
;
i
<
16
;
i
++
)
{
info
=
IRQ_ports
[
i
];
if
(
!
info
)
...
...
@@ -760,14 +762,17 @@ static void rs_timer(void)
serial_out
(
info
,
UART_IER
,
info
->
IER
);
info
=
info
->
next_port
;
}
while
(
info
);
rs_interrupt
(
i
,
NULL
);
if
(
rs_multiport
[
i
].
port1
)
rs_interrupt_multi
(
i
,
NULL
);
else
rs_interrupt
(
i
,
NULL
);
}
else
rs_interrupt_single
(
i
,
NULL
);
sti
();
}
}
last_strobe
=
jiffies
;
timer_table
[
RS_TIMER
].
expires
=
jiffies
+
60
*
HZ
;
timer_table
[
RS_TIMER
].
expires
=
jiffies
+
RS_STROBE_TIME
*
HZ
;
timer_active
|=
1
<<
RS_TIMER
;
if
(
IRQ_ports
[
0
])
{
...
...
@@ -877,7 +882,11 @@ static int startup(struct async_struct * info)
* Clear the FIFO buffers and disable them
* (they will be reenabled in change_speed())
*/
if
(
info
->
type
==
PORT_16550A
)
{
if
(
info
->
type
==
PORT_16650
)
{
serial_outp
(
info
,
UART_FCR
,
(
UART_FCR_CLEAR_RCVR
|
UART_FCR_CLEAR_XMIT
));
info
->
xmit_fifo_size
=
1
;
/* disabled for now */
}
else
if
(
info
->
type
==
PORT_16550A
)
{
serial_outp
(
info
,
UART_FCR
,
(
UART_FCR_CLEAR_RCVR
|
UART_FCR_CLEAR_XMIT
));
info
->
xmit_fifo_size
=
16
;
...
...
@@ -906,7 +915,10 @@ static int startup(struct async_struct * info)
!
IRQ_ports
[
info
->
irq
]
->
next_port
))
{
if
(
IRQ_ports
[
info
->
irq
])
{
free_irq
(
info
->
irq
);
handler
=
rs_interrupt
;
if
(
rs_multiport
[
info
->
irq
].
port1
)
handler
=
rs_interrupt_multi
;
else
handler
=
rs_interrupt
;
}
else
handler
=
rs_interrupt_single
;
...
...
@@ -1148,6 +1160,18 @@ static void change_speed(struct async_struct *info)
fcr
=
UART_FCR_ENABLE_FIFO
|
UART_FCR_TRIGGER_1
;
else
fcr
=
UART_FCR_ENABLE_FIFO
|
UART_FCR_TRIGGER_8
;
}
else
if
(
info
->
type
==
PORT_16650
)
{
/*
* On the 16650, we disable the FIFOs altogether
* because of a design bug in how the implement
* things. We could support it by completely changing
* how we handle the interrupt driver, but not today....
*
* N.B. Because there's no way to set a FIFO trigger
* at 1 char, we'd probably disable at speed below
* 2400 baud anyway...
*/
fcr
=
0
;
}
else
fcr
=
0
;
...
...
@@ -1404,6 +1428,7 @@ static int get_serial_info(struct async_struct * info,
tmp
.
flags
=
info
->
flags
;
tmp
.
baud_base
=
info
->
baud_base
;
tmp
.
close_delay
=
info
->
close_delay
;
tmp
.
closing_wait
=
info
->
closing_wait
;
tmp
.
custom_divisor
=
info
->
custom_divisor
;
tmp
.
hub6
=
info
->
hub6
;
memcpy_tofs
(
retinfo
,
&
tmp
,
sizeof
(
*
retinfo
));
...
...
@@ -1471,6 +1496,7 @@ static int set_serial_info(struct async_struct * info,
info
->
custom_divisor
=
new_serial
.
custom_divisor
;
info
->
type
=
new_serial
.
type
;
info
->
close_delay
=
new_serial
.
close_delay
;
info
->
closing_wait
=
new_serial
.
closing_wait
;
release_region
(
info
->
port
,
8
);
if
(
change_port
||
change_irq
)
{
...
...
@@ -1676,6 +1702,101 @@ static int check_wild_interrupts(int doprint)
return
wild_interrupts
;
}
static
int
get_multiport_struct
(
struct
async_struct
*
info
,
struct
serial_multiport_struct
*
retinfo
)
{
struct
serial_multiport_struct
ret
;
struct
rs_multiport_struct
*
multi
;
multi
=
&
rs_multiport
[
info
->
irq
];
ret
.
port_monitor
=
multi
->
port_monitor
;
ret
.
port1
=
multi
->
port1
;
ret
.
mask1
=
multi
->
mask1
;
ret
.
match1
=
multi
->
match1
;
ret
.
port2
=
multi
->
port2
;
ret
.
mask2
=
multi
->
mask2
;
ret
.
match2
=
multi
->
match2
;
ret
.
port3
=
multi
->
port3
;
ret
.
mask3
=
multi
->
mask3
;
ret
.
match3
=
multi
->
match3
;
ret
.
port4
=
multi
->
port4
;
ret
.
mask4
=
multi
->
mask4
;
ret
.
match4
=
multi
->
match4
;
ret
.
irq
=
info
->
irq
;
memcpy_tofs
(
retinfo
,
&
ret
,
sizeof
(
*
retinfo
));
return
0
;
}
static
int
set_multiport_struct
(
struct
async_struct
*
info
,
struct
serial_multiport_struct
*
in_multi
)
{
struct
serial_multiport_struct
new_multi
;
struct
rs_multiport_struct
*
multi
;
int
was_multi
,
now_multi
;
int
retval
;
void
(
*
handler
)(
int
,
struct
pt_regs
*
);
if
(
!
suser
())
return
-
EPERM
;
if
(
!
in_multi
)
return
-
EFAULT
;
memcpy_fromfs
(
&
new_multi
,
in_multi
,
sizeof
(
struct
serial_multiport_struct
));
if
(
new_multi
.
irq
!=
info
->
irq
||
info
->
irq
==
0
||
!
IRQ_ports
[
info
->
irq
])
return
-
EINVAL
;
multi
=
&
rs_multiport
[
info
->
irq
];
was_multi
=
(
multi
->
port1
!=
0
);
multi
->
port_monitor
=
new_multi
.
port_monitor
;
multi
->
port1
=
new_multi
.
port1
;
multi
->
mask1
=
new_multi
.
mask1
;
multi
->
match1
=
new_multi
.
match1
;
multi
->
port2
=
new_multi
.
port2
;
multi
->
mask2
=
new_multi
.
mask2
;
multi
->
match2
=
new_multi
.
match2
;
multi
->
port3
=
new_multi
.
port3
;
multi
->
mask3
=
new_multi
.
mask3
;
multi
->
match3
=
new_multi
.
match3
;
multi
->
port4
=
new_multi
.
port4
;
multi
->
mask4
=
new_multi
.
mask4
;
multi
->
match4
=
new_multi
.
match4
;
now_multi
=
(
multi
->
port1
!=
0
);
if
(
IRQ_ports
[
info
->
irq
]
->
next_port
&&
(
was_multi
!=
now_multi
))
{
free_irq
(
info
->
irq
);
if
(
now_multi
)
handler
=
rs_interrupt_multi
;
else
handler
=
rs_interrupt
;
retval
=
request_irq
(
info
->
irq
,
handler
,
SA_INTERRUPT
,
"serial"
);
if
(
retval
)
{
printk
(
"Couldn't reallocate serial interrupt "
"driver!!
\n
"
);
}
}
return
0
;
}
static
int
rs_ioctl
(
struct
tty_struct
*
tty
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
...
...
@@ -1778,6 +1899,16 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
info
,
sizeof
(
struct
async_struct
));
return
0
;
case
TIOCSERGETMULTI
:
error
=
verify_area
(
VERIFY_WRITE
,
(
void
*
)
arg
,
sizeof
(
struct
serial_multiport_struct
));
if
(
error
)
return
error
;
return
get_multiport_struct
(
info
,
(
struct
serial_multiport_struct
*
)
arg
);
case
TIOCSERSETMULTI
:
return
set_multiport_struct
(
info
,
(
struct
serial_multiport_struct
*
)
arg
);
default:
return
-
ENOIOCTLCMD
;
}
...
...
@@ -1871,6 +2002,13 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
info
->
normal_termios
=
*
tty
->
termios
;
if
(
info
->
flags
&
ASYNC_CALLOUT_ACTIVE
)
info
->
callout_termios
=
*
tty
->
termios
;
/*
* Now we wait for the trnasmit buffer to clear; and we notify
* the line discpline only process XON/XOFF characters.
*/
tty
->
closing
=
1
;
if
(
info
->
closing_wait
!=
ASYNC_CLOSING_WAIT_NONE
)
tty_wait_until_sent
(
tty
,
info
->
closing_wait
);
/*
* At this point we stop accepting input. To do this, we
* disable the receive line status interrupts, and tell the
...
...
@@ -1881,7 +2019,6 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
info
->
read_status_mask
&=
~
UART_LSR_DR
;
if
(
info
->
flags
&
ASYNC_INITIALIZED
)
{
serial_out
(
info
,
UART_IER
,
info
->
IER
);
tty_wait_until_sent
(
tty
,
3000
);
/* 30 seconds timeout */
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
...
...
@@ -1901,6 +2038,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
tty
->
driver
.
flush_buffer
(
tty
);
if
(
tty
->
ldisc
.
flush_buffer
)
tty
->
ldisc
.
flush_buffer
(
tty
);
tty
->
closing
=
0
;
info
->
event
=
0
;
info
->
tty
=
0
;
if
(
tty
->
ldisc
.
num
!=
ldiscs
[
N_TTY
].
num
)
{
...
...
@@ -2155,7 +2293,7 @@ int rs_open(struct tty_struct *tty, struct file * filp)
*/
static
void
show_serial_version
(
void
)
{
printk
(
"Serial driver version 4.
00
with"
);
printk
(
"Serial driver version 4.
11
with"
);
#ifdef CONFIG_HUB6
printk
(
" HUB-6"
);
#define SERIAL_OPT
...
...
@@ -2329,6 +2467,10 @@ static void autoconfig(struct async_struct * info)
if
(
info
->
flags
&
ASYNC_AUTO_IRQ
)
info
->
irq
=
do_auto_irq
(
info
);
scratch2
=
serial_in
(
info
,
UART_LCR
);
serial_outp
(
info
,
UART_LCR
,
scratch2
|
UART_LCR_DLAB
);
serial_outp
(
info
,
UART_EFR
,
0
);
/* EFR is the same as FCR */
serial_outp
(
info
,
UART_LCR
,
scratch2
);
serial_outp
(
info
,
UART_FCR
,
UART_FCR_ENABLE_FIFO
);
scratch
=
serial_in
(
info
,
UART_IIR
)
>>
6
;
info
->
xmit_fifo_size
=
1
;
...
...
@@ -2343,8 +2485,15 @@ static void autoconfig(struct async_struct * info)
info
->
type
=
PORT_16550
;
break
;
case
3
:
info
->
type
=
PORT_16550A
;
info
->
xmit_fifo_size
=
16
;
serial_outp
(
info
,
UART_LCR
,
scratch2
|
UART_LCR_DLAB
);
if
(
serial_in
(
info
,
UART_EFR
)
==
0
)
{
info
->
type
=
PORT_16650
;
info
->
xmit_fifo_size
=
32
;
}
else
{
info
->
type
=
PORT_16550A
;
info
->
xmit_fifo_size
=
16
;
}
serial_outp
(
info
,
UART_LCR
,
scratch2
);
break
;
}
if
(
info
->
type
==
PORT_16450
)
{
...
...
@@ -2398,6 +2547,7 @@ long rs_init(long kmem_start)
for
(
i
=
0
;
i
<
16
;
i
++
)
{
IRQ_ports
[
i
]
=
0
;
IRQ_timeout
[
i
]
=
0
;
memset
(
&
rs_multiport
[
i
],
0
,
sizeof
(
struct
rs_multiport_struct
));
}
show_serial_version
();
...
...
@@ -2458,6 +2608,7 @@ long rs_init(long kmem_start)
info
->
type
=
PORT_UNKNOWN
;
info
->
custom_divisor
=
0
;
info
->
close_delay
=
50
;
info
->
closing_wait
=
3000
;
info
->
x_char
=
0
;
info
->
event
=
0
;
info
->
count
=
0
;
...
...
@@ -2493,6 +2644,9 @@ long rs_init(long kmem_start)
case
PORT_16550A
:
printk
(
" is a 16550A
\n
"
);
break
;
case
PORT_16650
:
printk
(
" is a 16650
\n
"
);
break
;
default:
printk
(
"
\n
"
);
break
;
...
...
drivers/char/tty_io.c
View file @
5d278332
...
...
@@ -452,6 +452,7 @@ void disassociate_ctty(int priv)
kill_pg
(
tty
->
pgrp
,
SIGCONT
,
priv
);
}
current
->
tty_old_pgrp
=
0
;
tty
->
session
=
0
;
tty
->
pgrp
=
-
1
;
...
...
@@ -1165,6 +1166,7 @@ static int tty_open(struct inode * inode, struct file * filp)
!
current
->
tty
&&
tty
->
session
==
0
)
{
current
->
tty
=
tty
;
current
->
tty_old_pgrp
=
0
;
tty
->
session
=
current
->
session
;
tty
->
pgrp
=
current
->
pgrp
;
}
...
...
@@ -1393,6 +1395,7 @@ static int tty_ioctl(struct inode * inode, struct file * file,
return
-
EPERM
;
}
current
->
tty
=
tty
;
current
->
tty_old_pgrp
=
0
;
tty
->
session
=
current
->
session
;
tty
->
pgrp
=
current
->
pgrp
;
return
0
;
...
...
drivers/net/README.wavelan
View file @
5d278332
#if defined(CONFIG_WAVELAN)
T
ue Jan 31 10:42:35
EST 1995
T
hu Feb 23 00:10:31
EST 1995
0. This document refers to Version 5 of the Linux WaveLAN device driver software.
It has been tested successfully under the 1.1.87 release of the Linux
kernel. It is `beta-test' software, so caveat emptor. Please report bugs
to me so that I can fix them quickly.
1. At present the driver only autoprobes for a WaveLAN card at I/O address 0x390.
1. At present the driver autoprobes for a WaveLAN card only at I/O address 0x390.
The version of the card that I use (NCR) supports four I/O addresses (selectable
via a pair of DIP switches). If you want the driver to autoprobe a different
subset of the four valid addresses then you will need to edit
...
...
@@ -28,20 +23,7 @@ Tue Jan 31 10:42:35 EST 1995
append ="ether=0,0x390,0x4321,eth0"
..
3. The files that comprise this software must be incorporated into the Linux
kernel source tree (usually rooted at /usr/src/linux). Following that a
"make clean; make config; make dep; make zImage" should produce a Linux
kernel incorporating the WaveLAN driver, ready for installation.
The files:
drivers/net/wavelan.[ch]
drivers/net/i82586.h
are unique to this package and simply may be moved into place. The
others are modified versions of pre-existing files and must
be incorporated more carefully. However, the regions of modified code
within these files are small and are bracketed by the preprocessor
symbol CONFIG_WAVELAN, so incorporation should be straightforward.
4. If you encounter any problems send me some email.
3. If you encounter any problems send me some email.
Good luck,
Bruce Janson (bruce@cs.usyd.edu.au)
...
...
drivers/net/wavelan.c
View file @
5d278332
...
...
@@ -21,6 +21,7 @@
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/io.h>
...
...
@@ -70,7 +71,7 @@ struct net_local
extern
int
wavelan_probe
(
device
*
);
/* See Space.c */
static
char
*
version
=
"wavelan.c:v
5 31/1
/95
\n
"
;
static
char
*
version
=
"wavelan.c:v
6 22/2
/95
\n
"
;
/*
* Entry point forward declarations.
...
...
@@ -103,14 +104,6 @@ static void wavelan_local_show(device *);
static
unsigned
int
wavelan_debug
=
WAVELAN_DEBUG
;
static
net_local
*
first_wavelan
=
(
net_local
*
)
0
;
static
void
busy_loop
(
int
i
)
{
while
(
i
--
>
0
)
;
}
static
unsigned
long
wavelan_splhi
(
void
)
...
...
@@ -150,7 +143,7 @@ hacr_write_slow(unsigned short ioaddr, int hacr)
{
hacr_write
(
ioaddr
,
hacr
);
/* delay might only be needed sometimes */
busy_loop
(
1000
);
udelay
(
1000
);
}
/*
...
...
@@ -444,11 +437,13 @@ wavelan_ack(device *dev)
set_chan_attn
(
ioaddr
,
lp
->
hacr
);
for
(
i
=
1000
000
;
i
>
0
;
i
--
)
for
(
i
=
1000
;
i
>
0
;
i
--
)
{
obram_read
(
ioaddr
,
scboff
(
OFFSET_SCB
,
scb_command
),
(
unsigned
char
*
)
&
scb_cs
,
sizeof
(
scb_cs
));
if
(
scb_cs
==
0
)
break
;
udelay
(
1000
);
}
if
(
i
<=
0
)
...
...
@@ -477,11 +472,13 @@ wavelan_synchronous_cmd(device *dev, char *str)
set_chan_attn
(
ioaddr
,
lp
->
hacr
);
for
(
i
=
64
000
;
i
>
0
;
i
--
)
for
(
i
=
64
;
i
>
0
;
i
--
)
{
obram_read
(
ioaddr
,
OFFSET_CU
,
(
unsigned
char
*
)
&
cb
,
sizeof
(
cb
));
if
(
cb
.
ac_status
&
AC_SFLD_C
)
break
;
udelay
(
1000
);
}
if
(
i
<=
0
||
!
(
cb
.
ac_status
&
AC_SFLD_OK
))
...
...
@@ -557,23 +554,27 @@ wavelan_hardware_reset(device *dev)
set_chan_attn
(
ioaddr
,
lp
->
hacr
);
for
(
i
=
1000
000
;
i
>
0
;
i
--
)
for
(
i
=
1000
;
i
>
0
;
i
--
)
{
obram_read
(
ioaddr
,
OFFSET_ISCP
,
(
unsigned
char
*
)
&
iscp
,
sizeof
(
iscp
));
if
(
iscp
.
iscp_busy
==
(
unsigned
short
)
0
)
break
;
udelay
(
1000
);
}
if
(
i
<=
0
)
printk
(
"%s: wavelan_hardware_reset(): iscp_busy timeout.
\n
"
,
dev
->
name
);
for
(
i
=
15
000
;
i
>
0
;
i
--
)
for
(
i
=
15
;
i
>
0
;
i
--
)
{
obram_read
(
ioaddr
,
OFFSET_SCB
,
(
unsigned
char
*
)
&
scb
,
sizeof
(
scb
));
if
(
scb
.
scb_status
==
(
SCB_ST_CX
|
SCB_ST_CNA
))
break
;
udelay
(
1000
);
}
if
(
i
<=
0
)
...
...
@@ -970,11 +971,13 @@ wavelan_ru_start(device *dev)
set_chan_attn
(
ioaddr
,
lp
->
hacr
);
for
(
i
=
1000
000
;
i
>
0
;
i
--
)
for
(
i
=
1000
;
i
>
0
;
i
--
)
{
obram_read
(
ioaddr
,
scboff
(
OFFSET_SCB
,
scb_command
),
(
unsigned
char
*
)
&
scb_cs
,
sizeof
(
scb_cs
));
if
(
scb_cs
==
0
)
break
;
udelay
(
1000
);
}
if
(
i
<=
0
)
...
...
@@ -1049,11 +1052,13 @@ wavelan_cu_start(device *dev)
set_chan_attn
(
ioaddr
,
lp
->
hacr
);
for
(
i
=
1000
000
;
i
>
0
;
i
--
)
for
(
i
=
1000
;
i
>
0
;
i
--
)
{
obram_read
(
ioaddr
,
scboff
(
OFFSET_SCB
,
scb_command
),
(
unsigned
char
*
)
&
scb_cs
,
sizeof
(
scb_cs
));
if
(
scb_cs
==
0
)
break
;
udelay
(
1000
);
}
if
(
i
<=
0
)
...
...
@@ -1849,6 +1854,7 @@ void
wavelan_set_multicast_list
(
device
*
dev
,
int
num_addrs
,
void
*
addrs
)
{
net_local
*
lp
;
unsigned
long
x
;
lp
=
(
net_local
*
)
dev
->
priv
;
...
...
@@ -1859,7 +1865,9 @@ wavelan_set_multicast_list(device *dev, int num_addrs, void *addrs)
* Promiscuous mode: receive all packets.
*/
lp
->
promiscuous
=
1
;
x
=
wavelan_splhi
();
(
void
)
wavelan_hardware_reset
(
dev
);
wavelan_splx
(
x
);
break
;
case
0
:
...
...
@@ -1868,7 +1876,9 @@ wavelan_set_multicast_list(device *dev, int num_addrs, void *addrs)
* clear multicast list.
*/
lp
->
promiscuous
=
0
;
x
=
wavelan_splhi
();
(
void
)
wavelan_hardware_reset
(
dev
);
wavelan_splx
(
x
);
break
;
default:
...
...
@@ -2319,9 +2329,9 @@ wavelan_local_show(device *dev)
* Allan Creighton (allanc@cs.usyd.edu.au),
* Matthew Geier (matthew@cs.usyd.edu.au),
* Remo di Giovanni (remo@cs.usyd.edu.au),
* Eckhard Grah (grah@wrcs1.urz.uni-wuppertal.de),
* Mark Hagan (mhagan@wtcpost.daytonoh.NCR.COM),
* Tim Nicholson (tim@cs.usyd.edu.au),
* Jeff Noxon (jeff@oylpatch.sccsi.com),
* Ian Parkin (ian@cs.usyd.edu.au),
* John Rosenberg (johnr@cs.usyd.edu.au),
* George Rossi (george@phm.gov.au),
...
...
fs/buffer.c
View file @
5d278332
...
...
@@ -1363,7 +1363,7 @@ static int shrink_specific_buffers(unsigned int priority, int size)
if
(
priority
>
3
&&
nlist
==
BUF_SHARED
)
continue
;
bh
=
lru_list
[
nlist
];
if
(
!
bh
)
continue
;
i
=
nr_buffers_type
[
nlist
]
>>
priority
;
i
=
2
*
nr_buffers_type
[
nlist
]
>>
priority
;
for
(
;
i
--
>
0
;
bh
=
bh
->
b_next_free
)
{
/* We may have stalled while waiting for I/O to complete. */
if
(
bh
->
b_list
!=
nlist
)
goto
repeat1
;
...
...
fs/isofs/dir.c
View file @
5d278332
...
...
@@ -183,14 +183,17 @@ static int isofs_readdir(struct inode * inode, struct file * filp,
is no Rock Ridge NM field. */
else
{
/* Do not report hidden or associated files */
high_sierra
=
inode
->
i_sb
->
u
.
isofs_sb
.
s_high_sierra
;
if
(
de
->
flags
[
-
high_sierra
]
&
5
)
{
if
(
cpnt
)
{
kfree
(
cpnt
);
cpnt
=
NULL
;
};
continue
;
if
(
inode
->
i_sb
->
u
.
isofs_sb
.
s_unhide
==
'n'
)
{
/* Do not report hidden or associated files */
high_sierra
=
inode
->
i_sb
->
u
.
isofs_sb
.
s_high_sierra
;
if
(
de
->
flags
[
-
high_sierra
]
&
5
)
{
if
(
cpnt
)
{
kfree
(
cpnt
);
cpnt
=
NULL
;
};
continue
;
}
}
dlen
=
de
->
name_len
[
0
];
dpnt
=
de
->
name
;
...
...
fs/isofs/inode.c
View file @
5d278332
...
...
@@ -63,6 +63,7 @@ struct iso9660_options{
char
map
;
char
rock
;
char
cruft
;
char
unhide
;
unsigned
char
conversion
;
unsigned
int
blocksize
;
mode_t
mode
;
...
...
@@ -77,6 +78,7 @@ static int parse_options(char *options, struct iso9660_options * popt)
popt
->
map
=
'n'
;
popt
->
rock
=
'y'
;
popt
->
cruft
=
'n'
;
popt
->
unhide
=
'n'
;
popt
->
conversion
=
'a'
;
popt
->
blocksize
=
1024
;
popt
->
mode
=
S_IRUGO
;
...
...
@@ -88,6 +90,10 @@ static int parse_options(char *options, struct iso9660_options * popt)
popt
->
rock
=
'n'
;
continue
;
};
if
(
strncmp
(
this_char
,
"unhide"
,
6
)
==
0
)
{
popt
->
unhide
=
'y'
;
continue
;
};
if
(
strncmp
(
this_char
,
"cruft"
,
5
)
==
0
)
{
popt
->
cruft
=
'y'
;
continue
;
...
...
@@ -214,6 +220,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
printk("map = %c\n", opt.map);
printk("rock = %c\n", opt.rock);
printk("cruft = %c\n", opt.cruft);
printk("unhide = %c\n", opt.unhide);
printk("conversion = %c\n", opt.conversion);
printk("blocksize = %d\n", opt.blocksize);
printk("gid = %d\n", opt.gid);
...
...
@@ -353,6 +360,7 @@ struct super_block *isofs_read_super(struct super_block *s,void *data,
s
->
u
.
isofs_sb
.
s_rock
=
(
opt
.
rock
==
'y'
?
1
:
0
);
s
->
u
.
isofs_sb
.
s_conversion
=
opt
.
conversion
;
s
->
u
.
isofs_sb
.
s_cruft
=
opt
.
cruft
;
s
->
u
.
isofs_sb
.
s_unhide
=
opt
.
unhide
;
s
->
u
.
isofs_sb
.
s_uid
=
opt
.
uid
;
s
->
u
.
isofs_sb
.
s_gid
=
opt
.
gid
;
/*
...
...
fs/isofs/namei.c
View file @
5d278332
...
...
@@ -73,7 +73,6 @@ static struct buffer_head * isofs_find_entry(struct inode * dir,
unsigned
int
old_offset
;
unsigned
int
backlink
;
int
dlen
,
rrflag
,
match
;
int
high_sierra
=
0
;
char
*
dpnt
;
struct
iso_directory_record
*
de
;
char
c
;
...
...
@@ -155,16 +154,6 @@ static struct buffer_head * isofs_find_entry(struct inode * dir,
backlink
=
0
;
}
/* Do not report hidden or associated files */
high_sierra
=
dir
->
i_sb
->
u
.
isofs_sb
.
s_high_sierra
;
if
(
de
->
flags
[
-
high_sierra
]
&
5
)
{
if
(
cpnt
)
{
kfree
(
cpnt
);
cpnt
=
NULL
;
};
continue
;
}
dlen
=
de
->
name_len
[
0
];
dpnt
=
de
->
name
;
/* Now convert the filename in the buffer to lower case */
...
...
fs/locks.c
View file @
5d278332
...
...
@@ -7,7 +7,7 @@
* Deadlock Detection added by Kelly Carmichael, kelly@[142.24.8.65]
* September 17, 1994.
*
* FIXME: one thing isn't handled yet:
*
FIXME: one thing isn't handled yet:
* - mandatory locks (requires lots of changes elsewhere)
*
* Edited by Kai Petzke, wpp@marie.physik.tu-berlin.de
...
...
@@ -22,7 +22,11 @@
* process. Since locks still depend on the process id, locks are inherited
* after an exec() but not after a fork(). This agrees with POSIX, and both
* BSD and SVR4 practice.
* Andy Walker (andy@keo.kvaerner.no), February 14, 1994
* Andy Walker (andy@keo.kvaerner.no), February 14, 1995
*
* Scrapped free list which is redundant now that we allocate locks
* dynamically with kmalloc()/kfree().
* Andy Walker (andy@keo.kvaerner.no), February 21, 1995
*
*/
...
...
@@ -45,16 +49,11 @@ static int overlap(struct file_lock *fl1, struct file_lock *fl2);
static
int
lock_it
(
struct
file
*
filp
,
struct
file_lock
*
caller
);
static
struct
file_lock
*
alloc_lock
(
struct
file_lock
**
pos
,
struct
file_lock
*
fl
);
static
void
free_lock
(
struct
file_lock
**
fl
);
static
void
free_list_garbage_collect
(
void
);
#ifdef DEADLOCK_DETECTION
int
locks_deadlocked
(
int
my_pid
,
int
blocked_pid
);
#endif
#define FREE_LIST_GARBAGE_COLLECT 20
static
struct
file_lock
*
file_lock_table
=
NULL
;
static
struct
file_lock
*
file_lock_free_list
=
NULL
;
static
int
free_list_cnt
=
0
;
int
fcntl_getlk
(
unsigned
int
fd
,
struct
flock
*
l
)
{
...
...
@@ -155,7 +154,8 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
if
(
current
->
signal
&
~
current
->
blocked
)
return
-
ERESTARTSYS
;
#ifdef DEADLOCK_DETECTION
if
(
locks_deadlocked
(
file_lock
.
fl_owner
->
pid
,
fl
->
fl_owner
->
pid
))
return
-
EDEADLOCK
;
if
(
locks_deadlocked
(
file_lock
.
fl_owner
->
pid
,
fl
->
fl_owner
->
pid
))
return
-
EDEADLOCK
;
#endif
interruptible_sleep_on
(
&
fl
->
fl_wait
);
if
(
current
->
signal
&
~
current
->
blocked
)
...
...
@@ -192,9 +192,11 @@ int locks_deadlocked(int my_pid,int blocked_pid)
dlock_wait
=
fl
->
fl_wait
;
do
{
if
(
dlock_wait
->
task
!=
NULL
)
{
if
(
dlock_wait
->
task
->
pid
==
blocked_pid
)
return
-
EDEADLOCK
;
if
(
dlock_wait
->
task
->
pid
==
blocked_pid
)
return
-
EDEADLOCK
;
ret_val
=
locks_deadlocked
(
dlock_wait
->
task
->
pid
,
blocked_pid
);
if
(
ret_val
)
return
-
EDEADLOCK
;
if
(
ret_val
)
return
-
EDEADLOCK
;
}
dlock_wait
=
dlock_wait
->
next
;
}
while
(
dlock_wait
!=
fl
->
fl_wait
);
...
...
@@ -445,40 +447,26 @@ static int lock_it(struct file *filp, struct file_lock *caller)
/*
* File_lock() inserts a lock at the position pos of the linked list.
*
* Modified to create a new node if no free entries available - Chad Page
*
*/
static
struct
file_lock
*
alloc_lock
(
struct
file_lock
**
pos
,
struct
file_lock
*
fl
)
{
struct
file_lock
*
tmp
;
tmp
=
file_lock_free_list
;
if
(
tmp
==
NULL
)
{
/* Okay, let's make a new file_lock structure... */
tmp
=
(
struct
file_lock
*
)
kmalloc
(
sizeof
(
struct
file_lock
),
GFP_KERNEL
);
tmp
->
fl_owner
=
NULL
;
tmp
->
fl_next
=
file_lock_free_list
;
tmp
->
fl_nextlink
=
file_lock_table
;
file_lock_table
=
tmp
;
}
else
{
/* remove from free list */
file_lock_free_list
=
tmp
->
fl_next
;
free_list_cnt
--
;
}
if
(
tmp
->
fl_owner
!=
NULL
)
panic
(
"alloc_lock: broken free list
\n
"
);
/* Okay, let's make a new file_lock structure... */
tmp
=
(
struct
file_lock
*
)
kmalloc
(
sizeof
(
struct
file_lock
),
GFP_KERNEL
);
if
(
!
tmp
)
return
tmp
;
tmp
->
fl_nextlink
=
file_lock_table
;
tmp
->
fl_prevlink
=
NULL
;
if
(
file_lock_table
!=
NULL
)
file_lock_table
->
fl_prevlink
=
tmp
;
file_lock_table
=
tmp
;
tmp
->
fl_next
=
*
pos
;
/* insert into file's list */
*
pos
=
tmp
;
tmp
->
fl_owner
=
current
;
/* FIXME: needed? */
tmp
->
fl_owner
=
current
;
tmp
->
fl_wait
=
NULL
;
tmp
->
fl_type
=
fl
->
fl_type
;
...
...
@@ -490,7 +478,7 @@ static struct file_lock *alloc_lock(struct file_lock **pos,
}
/*
*
Add a lock to the free list
...
*
Free up a lock
...
*/
static
void
free_lock
(
struct
file_lock
**
fl_p
)
...
...
@@ -498,24 +486,19 @@ static void free_lock(struct file_lock **fl_p)
struct
file_lock
*
fl
;
fl
=
*
fl_p
;
if
(
fl
->
fl_owner
==
NULL
)
/* sanity check */
panic
(
"free_lock: broken lock list
\n
"
);
*
fl_p
=
(
*
fl_p
)
->
fl_next
;
fl
->
fl_next
=
file_lock_free_list
;
/* add to free list */
file_lock_free_list
=
fl
;
fl
->
fl_owner
=
NULL
;
/* for sanity checks */
if
(
fl
->
fl_nextlink
!=
NULL
)
fl
->
fl_nextlink
->
fl_prevlink
=
fl
->
fl_prevlink
;
free_list_cnt
++
;
if
(
free_list_cnt
==
FREE_LIST_GARBAGE_COLLECT
)
free_list_garbage_collect
();
if
(
fl
->
fl_prevlink
!=
NULL
)
fl
->
fl_prevlink
->
fl_nextlink
=
fl
->
fl_nextlink
;
else
file_lock_table
=
fl
->
fl_nextlink
;
wake_up
(
&
fl
->
fl_wait
);
}
static
void
free_list_garbage_collect
(
void
)
{
/* Do nothing for now */
kfree
(
fl
);
return
;
}
fs/proc/mem.c
View file @
5d278332
#define THREE_LEVEL
/*
* linux/fs/proc/mem.c
*
...
...
@@ -25,7 +26,8 @@
static
int
mem_read
(
struct
inode
*
inode
,
struct
file
*
file
,
char
*
buf
,
int
count
)
{
pgd_t
*
pgdir
;
pgd_t
*
page_dir
;
pmd_t
*
page_middle
;
pte_t
pte
;
char
*
page
;
struct
task_struct
*
tsk
;
...
...
@@ -50,15 +52,23 @@ static int mem_read(struct inode * inode, struct file * file,char * buf, int cou
while
(
count
>
0
)
{
if
(
current
->
signal
&
~
current
->
blocked
)
break
;
p
gdir
=
PAGE_DIR_OFFSET
(
tsk
,
addr
);
if
(
pgd_none
(
*
p
g
dir
))
p
age_dir
=
pgd_offset
(
tsk
,
addr
);
if
(
pgd_none
(
*
p
age_
dir
))
break
;
if
(
pgd_bad
(
*
p
g
dir
))
{
printk
(
"Bad page dir entry %08lx
\n
"
,
pgd_val
(
*
p
g
dir
));
pgd_clear
(
p
g
dir
);
if
(
pgd_bad
(
*
p
age_
dir
))
{
printk
(
"Bad page dir entry %08lx
\n
"
,
pgd_val
(
*
p
age_
dir
));
pgd_clear
(
p
age_
dir
);
break
;
}
pte
=
*
(
pte_t
*
)
(
PAGE_PTR
(
addr
)
+
pgd_page
(
*
pgdir
));
page_middle
=
pmd_offset
(
page_dir
,
addr
);
if
(
pmd_none
(
*
page_middle
))
break
;
if
(
pmd_bad
(
*
page_middle
))
{
printk
(
"Bad page middle entry %08lx
\n
"
,
pmd_val
(
*
page_middle
));
pmd_clear
(
page_middle
);
break
;
}
pte
=
*
pte_offset
(
page_middle
,
addr
);
if
(
!
pte_present
(
pte
))
break
;
page
=
(
char
*
)
pte_page
(
pte
)
+
(
addr
&
~
PAGE_MASK
);
...
...
@@ -78,8 +88,9 @@ static int mem_read(struct inode * inode, struct file * file,char * buf, int cou
static
int
mem_write
(
struct
inode
*
inode
,
struct
file
*
file
,
char
*
buf
,
int
count
)
{
pgd_t
*
pgdir
;
pte_t
*
pte
;
pgd_t
*
page_dir
;
pmd_t
*
page_middle
;
pte_t
pte
;
char
*
page
;
struct
task_struct
*
tsk
;
unsigned
long
addr
,
pid
;
...
...
@@ -103,15 +114,23 @@ static int mem_write(struct inode * inode, struct file * file,char * buf, int co
while
(
count
>
0
)
{
if
(
current
->
signal
&
~
current
->
blocked
)
break
;
p
gdir
=
PAGE_DIR_OFFSET
(
tsk
,
addr
);
if
(
pgd_none
(
*
p
g
dir
))
p
age_dir
=
pgd_offset
(
tsk
,
addr
);
if
(
pgd_none
(
*
p
age_
dir
))
break
;
if
(
pgd_bad
(
*
p
g
dir
))
{
printk
(
"Bad page dir entry %08lx
\n
"
,
pgd_val
(
*
p
g
dir
));
pgd_clear
(
p
g
dir
);
if
(
pgd_bad
(
*
p
age_
dir
))
{
printk
(
"Bad page dir entry %08lx
\n
"
,
pgd_val
(
*
p
age_
dir
));
pgd_clear
(
p
age_
dir
);
break
;
}
pte
=
*
(
pte_t
*
)
(
PAGE_PTR
(
addr
)
+
pgd_page
(
*
pgdir
));
page_middle
=
pmd_offset
(
page_dir
,
addr
);
if
(
pmd_none
(
*
page_middle
))
break
;
if
(
pmd_bad
(
*
page_middle
))
{
printk
(
"Bad page middle entry %08lx
\n
"
,
pmd_val
(
*
page_middle
));
pmd_clear
(
page_middle
);
break
;
}
pte
=
*
pte_offset
(
page_middle
,
addr
);
if
(
!
pte_present
(
pte
))
break
;
if
(
!
pte_write
(
pte
))
...
...
@@ -157,6 +176,7 @@ int mem_mmap(struct inode * inode, struct file * file,
{
struct
task_struct
*
tsk
;
pgd_t
*
src_dir
,
*
dest_dir
;
pmd_t
*
src_middle
,
*
dest_middle
;
pte_t
*
src_table
,
*
dest_table
;
unsigned
long
stmp
,
dtmp
;
struct
vm_area_struct
*
src_vma
=
NULL
;
...
...
@@ -168,7 +188,6 @@ int mem_mmap(struct inode * inode, struct file * file,
for
(
i
=
1
;
i
<
NR_TASKS
;
i
++
)
if
(
task
[
i
]
&&
task
[
i
]
->
pid
==
(
inode
->
i_ino
>>
16
))
{
tsk
=
task
[
i
];
src_vma
=
task
[
i
]
->
mm
->
mmap
;
break
;
}
...
...
@@ -180,6 +199,7 @@ int mem_mmap(struct inode * inode, struct file * file,
moment because working out the vm_area_struct & nattach stuff isn't
worth it. */
src_vma
=
tsk
->
mm
->
mmap
;
stmp
=
vma
->
vm_offset
;
while
(
stmp
<
vma
->
vm_offset
+
(
vma
->
vm_end
-
vma
->
vm_start
))
{
while
(
src_vma
&&
stmp
>
src_vma
->
vm_end
)
...
...
@@ -187,15 +207,21 @@ int mem_mmap(struct inode * inode, struct file * file,
if
(
!
src_vma
||
(
src_vma
->
vm_flags
&
VM_SHM
))
return
-
EINVAL
;
src_dir
=
PAGE_DIR_OFFSET
(
tsk
,
stmp
);
src_dir
=
pgd_offset
(
tsk
,
stmp
);
if
(
pgd_none
(
*
src_dir
))
return
-
EINVAL
;
if
(
pgd_bad
(
*
src_dir
))
{
printk
(
"Bad source page dir entry %08lx
\n
"
,
pgd_val
(
*
src_dir
));
return
-
EINVAL
;
}
src_table
=
(
pte_t
*
)(
pgd_page
(
*
src_dir
)
+
PAGE_PTR
(
stmp
));
src_middle
=
pmd_offset
(
src_dir
,
stmp
);
if
(
pmd_none
(
*
src_middle
))
return
-
EINVAL
;
if
(
pmd_bad
(
*
src_middle
))
{
printk
(
"Bad source page middle entry %08lx
\n
"
,
pmd_val
(
*
src_middle
));
return
-
EINVAL
;
}
src_table
=
pte_offset
(
src_middle
,
stmp
);
if
(
pte_none
(
*
src_table
))
return
-
EINVAL
;
...
...
@@ -208,7 +234,7 @@ int mem_mmap(struct inode * inode, struct file * file,
stmp
+=
PAGE_SIZE
;
}
src_vma
=
t
ask
[
i
]
->
mm
->
mmap
;
src_vma
=
t
sk
->
mm
->
mmap
;
stmp
=
vma
->
vm_offset
;
dtmp
=
vma
->
vm_start
;
...
...
@@ -216,28 +242,17 @@ int mem_mmap(struct inode * inode, struct file * file,
while
(
src_vma
&&
stmp
>
src_vma
->
vm_end
)
src_vma
=
src_vma
->
vm_next
;
src_dir
=
PAGE_DIR_OFFSET
(
tsk
,
stmp
);
src_table
=
(
pte_t
*
)
(
pgd_page
(
*
src_dir
)
+
PAGE_PTR
(
stmp
));
dest_dir
=
PAGE_DIR_OFFSET
(
current
,
dtmp
);
if
(
pgd_none
(
*
dest_dir
))
{
unsigned
long
page
=
get_free_page
(
GFP_KERNEL
);
if
(
!
page
)
return
-
ENOMEM
;
if
(
pgd_none
(
*
dest_dir
))
{
pgd_set
(
dest_dir
,
(
pte_t
*
)
page
);
}
else
{
free_page
(
page
);
}
}
if
(
pgd_bad
(
*
dest_dir
))
{
printk
(
"Bad dest directory entry %08lx
\n
"
,
pgd_val
(
*
dest_dir
));
return
-
EINVAL
;
}
dest_table
=
(
pte_t
*
)
(
pgd_page
(
*
dest_dir
)
+
PAGE_PTR
(
dtmp
));
src_dir
=
pgd_offset
(
tsk
,
stmp
);
src_middle
=
pmd_offset
(
src_dir
,
stmp
);
src_table
=
pte_offset
(
src_middle
,
stmp
);
dest_dir
=
pgd_offset
(
current
,
dtmp
);
dest_middle
=
pmd_alloc
(
dest_dir
,
dtmp
);
if
(
!
dest_middle
)
return
-
ENOMEM
;
dest_table
=
pte_alloc
(
dest_middle
,
dtmp
);
if
(
!
dest_table
)
return
-
ENOMEM
;
if
(
!
pte_present
(
*
src_table
))
do_no_page
(
src_vma
,
stmp
,
1
);
...
...
include/asm-alpha/byteorder.h
View file @
5d278332
...
...
@@ -32,14 +32,11 @@ __ntohl(unsigned long int x)
((
x
&
0xff000000U
)
>>
24
));
}
extern
__inline__
unsigned
long
int
__constant_ntohl
(
unsigned
long
int
x
)
{
return
(((
x
&
0x000000ffU
)
<<
24
)
|
((
x
&
0x0000ff00U
)
<<
8
)
|
((
x
&
0x00ff0000U
)
>>
8
)
|
((
x
&
0xff000000U
)
>>
24
));
}
#define __constant_ntohl(x) \
((unsigned int)((((unsigned int)(x) & 0x000000ffU) << 24) | \
(((unsigned int)(x) & 0x0000ff00U) << 8) | \
(((unsigned int)(x) & 0x00ff0000U) >> 8) | \
(((unsigned int)(x) & 0xff000000U) >> 24)))
extern
__inline__
unsigned
short
int
__ntohs
(
unsigned
short
int
x
)
...
...
@@ -48,12 +45,9 @@ __ntohs(unsigned short int x)
((
x
&
0xff00
)
>>
8
));
}
extern
__inline__
unsigned
short
int
__constant_ntohs
(
unsigned
short
int
x
)
{
return
(((
x
&
0x00ff
)
<<
8
)
|
((
x
&
0xff00
)
>>
8
));
}
#define __constant_ntohs(x) \
((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
(((unsigned short int)(x) & 0xff00) >> 8)))
#define __htonl(x) __ntohl(x)
#define __htons(x) __ntohs(x)
...
...
include/asm-alpha/pgtable.h
View file @
5d278332
...
...
@@ -160,18 +160,33 @@ extern inline int pte_none(pte_t pte) { return !pte_val(pte); }
extern
inline
int
pte_present
(
pte_t
pte
)
{
return
pte_val
(
pte
)
&
_PAGE_VALID
;
}
extern
inline
int
pte_inuse
(
pte_t
*
ptep
)
{
return
mem_map
[
MAP_NR
(
ptep
)]
>
1
;
}
extern
inline
void
pte_clear
(
pte_t
*
ptep
)
{
pte_val
(
*
ptep
)
=
0
;
}
extern
inline
void
pte_reuse
(
pte_t
*
ptep
)
{
if
(
!
(
mem_map
[
MAP_NR
(
ptep
)]
&
MAP_PAGE_RESERVED
))
mem_map
[
MAP_NR
(
ptep
)]
++
;
}
extern
inline
int
pmd_none
(
pmd_t
pmd
)
{
return
!
pmd_val
(
pmd
);
}
extern
inline
int
pmd_bad
(
pmd_t
pmd
)
{
return
(
pmd_val
(
pmd
)
&
~
_PFN_MASK
)
!=
_PAGE_TABLE
||
pmd_page
(
pmd
)
>
high_memory
;
}
extern
inline
int
pmd_present
(
pmd_t
pmd
)
{
return
pmd_val
(
pmd
)
&
_PAGE_VALID
;
}
extern
inline
int
pmd_inuse
(
pmd_t
*
pmdp
)
{
return
mem_map
[
MAP_NR
(
pmdp
)]
>
1
;
}
extern
inline
void
pmd_clear
(
pmd_t
*
pmdp
)
{
pmd_val
(
*
pmdp
)
=
0
;
}
extern
inline
void
pmd_reuse
(
pmd_t
*
pmdp
)
{
if
(
!
(
mem_map
[
MAP_NR
(
pmdp
)]
&
MAP_PAGE_RESERVED
))
mem_map
[
MAP_NR
(
pmdp
)]
++
;
}
extern
inline
int
pgd_none
(
pgd_t
pgd
)
{
return
!
pgd_val
(
pgd
);
}
extern
inline
int
pgd_bad
(
pgd_t
pgd
)
{
return
(
pgd_val
(
pgd
)
&
~
_PFN_MASK
)
!=
_PAGE_TABLE
||
pgd_page
(
pgd
)
>
high_memory
;
}
extern
inline
int
pgd_present
(
pgd_t
pgd
)
{
return
pgd_val
(
pgd
)
&
_PAGE_VALID
;
}
extern
inline
int
pgd_inuse
(
pgd_t
*
pgdp
)
{
return
mem_map
[
MAP_NR
(
pgdp
)]
>
1
;
}
extern
inline
void
pgd_clear
(
pgd_t
*
pgdp
)
{
pgd_val
(
*
pgdp
)
=
0
;
}
extern
inline
void
pgd_reuse
(
pgd_t
*
pgdp
)
{
if
(
!
(
mem_map
[
MAP_NR
(
pgdp
)]
&
MAP_PAGE_RESERVED
))
mem_map
[
MAP_NR
(
pgdp
)]
++
;
}
/*
* The following only work if pte_present() is true.
...
...
include/asm-i386/byteorder.h
View file @
5d278332
...
...
@@ -27,14 +27,11 @@ __ntohl(unsigned long int x)
return
x
;
}
extern
__inline__
unsigned
long
int
__constant_ntohl
(
unsigned
long
int
x
)
{
return
(((
x
&
0x000000ffU
)
<<
24
)
|
((
x
&
0x0000ff00U
)
<<
8
)
|
((
x
&
0x00ff0000U
)
>>
8
)
|
((
x
&
0xff000000U
)
>>
24
));
}
#define __constant_ntohl(x) \
((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \
(((unsigned long int)(x) & 0x0000ff00U) << 8) | \
(((unsigned long int)(x) & 0x00ff0000U) >> 8) | \
(((unsigned long int)(x) & 0xff000000U) >> 24)))
extern
__inline__
unsigned
short
int
__ntohs
(
unsigned
short
int
x
)
...
...
@@ -45,12 +42,9 @@ __ntohs(unsigned short int x)
return
x
;
}
extern
__inline__
unsigned
short
int
__constant_ntohs
(
unsigned
short
int
x
)
{
return
(((
x
&
0x00ff
)
<<
8
)
|
((
x
&
0xff00
)
>>
8
));
}
#define __constant_ntohs(x) \
((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \
(((unsigned short int)(x) & 0xff00) >> 8))) \
#define __htonl(x) __ntohl(x)
#define __htons(x) __ntohs(x)
...
...
include/asm-sparc/system.h
View file @
5d278332
#ifndef __SPARC_SYSTEM_H
#define __SPARC_SYSTEM_H
#include <asm/segment.h>
/*
* System defines.. Note that this is included both from .c and .S
* files, so it does only defines, not any C code.
...
...
include/asm-sparc/vac-ops.h
View file @
5d278332
...
...
@@ -7,8 +7,8 @@
Copyright (C) 1994, David S. Miller (davem@caip.rutgers.edu)
*/
extern
unsigned
int
trapbase
[]
;
extern
unsigned
int
end
[],
etext
[],
msgbuf
[]
;
extern
unsigned
long
*
trapbase
;
extern
char
end
,
etext
,
msgbuf
;
extern
void
flush_vac_context
(
void
);
extern
void
flush_vac_segment
(
unsigned
int
foo_segment
);
...
...
include/linux/fs.h
View file @
5d278332
...
...
@@ -266,8 +266,9 @@ struct file {
};
struct
file_lock
{
struct
file_lock
*
fl_next
;
/* singly linked list */
struct
file_lock
*
fl_nextlink
;
struct
file_lock
*
fl_next
;
/* singly linked list for this inode (or the free list) */
struct
file_lock
*
fl_nextlink
;
/* doubly linked list of all locks */
struct
file_lock
*
fl_prevlink
;
/* used to simplify garbage collecting */
struct
task_struct
*
fl_owner
;
/* NULL if on free list, for sanity checks */
struct
wait_queue
*
fl_wait
;
char
fl_type
;
...
...
include/linux/iso_fs_sb.h
View file @
5d278332
...
...
@@ -18,6 +18,7 @@ struct isofs_sb_info {
unsigned
char
s_cruft
;
/* Broken disks with high
byte of length containing
junk */
unsigned
char
s_unhide
;
unsigned
char
s_nosuid
;
unsigned
char
s_nodev
;
mode_t
s_mode
;
...
...
include/linux/sched.h
View file @
5d278332
...
...
@@ -268,11 +268,12 @@ extern int request_irq(unsigned int irq,void (*handler)(int, struct pt_regs *),
unsigned
long
flags
,
const
char
*
device
);
extern
void
free_irq
(
unsigned
int
irq
);
extern
unsigned
long
copy_thread
(
int
,
unsigned
long
,
struct
task_struct
*
,
struct
pt_regs
*
);
extern
void
copy_thread
(
int
,
unsigned
long
,
unsigned
long
,
struct
task_struct
*
,
struct
pt_regs
*
);
extern
void
flush_thread
(
void
);
extern
void
exit_thread
(
void
);
extern
int
do_execve
(
char
*
,
char
**
,
char
**
,
struct
pt_regs
*
);
extern
int
do_fork
(
unsigned
long
,
unsigned
long
,
struct
pt_regs
*
);
asmlinkage
int
do_signal
(
unsigned
long
,
struct
pt_regs
*
);
/*
...
...
include/linux/serial.h
View file @
5d278332
...
...
@@ -22,9 +22,18 @@ struct serial_struct {
unsigned
short
close_delay
;
char
reserved_char
[
2
];
int
hub6
;
int
reserved
[
5
];
unsigned
short
closing_wait
;
/* time to wait before closing */
unsigned
short
closing_wait2
;
/* no longer used... */
int
reserved
[
4
];
};
/*
* For the close wait times, 0 means wait forever for serial port to
* flush its output. 65535 means don't wait at all.
*/
#define ASYNC_CLOSING_WAIT_INF 0
#define ASYNC_CLOSING_WAIT_NONE 65535
/*
* These are the supported serial types.
*/
...
...
@@ -34,7 +43,8 @@ struct serial_struct {
#define PORT_16550 3
#define PORT_16550A 4
#define PORT_CIRRUS 5
#define PORT_MAX 5
#define PORT_16650 6
#define PORT_MAX 6
/*
* Definitions for async_struct (and serial_struct) flags field
...
...
@@ -70,6 +80,23 @@ struct serial_struct {
#define ASYNC_CTS_FLOW 0x04000000
/* Do CTS flow control */
#define ASYNC_CHECK_CD 0x02000000
/* i.e., CLOCAL */
/*
* Multiport serial configuration structure --- external structure
*/
struct
serial_multiport_struct
{
int
irq
;
int
port1
;
unsigned
char
mask1
,
match1
;
int
port2
;
unsigned
char
mask2
,
match2
;
int
port3
;
unsigned
char
mask3
,
match3
;
int
port4
;
unsigned
char
mask4
,
match4
;
int
port_monitor
;
int
reserved
[
32
];
};
#ifdef __KERNEL__
/*
* This is our internal structure for each serial port's state.
...
...
@@ -96,6 +123,8 @@ struct async_struct {
int
custom_divisor
;
int
x_char
;
/* xon/xoff character */
int
close_delay
;
unsigned
short
closing_wait
;
unsigned
short
closing_wait2
;
int
IER
;
/* Interrupt Enable Register */
int
MCR
;
/* Modem control register */
int
MCR_noint
;
/* MCR with interrupts off */
...
...
@@ -133,6 +162,21 @@ struct async_struct {
#define RS_EVENT_WRITE_WAKEUP 0
#define RS_EVENT_HANGUP 1
/*
* Multiport serial configuration structure --- internal structure
*/
struct
rs_multiport_struct
{
int
port1
;
unsigned
char
mask1
,
match1
;
int
port2
;
unsigned
char
mask2
,
match2
;
int
port3
;
unsigned
char
mask3
,
match3
;
int
port4
;
unsigned
char
mask4
,
match4
;
int
port_monitor
;
};
/* Export to allow PCMCIA to use this - Dave Hinds */
extern
int
register_serial
(
struct
serial_struct
*
req
);
extern
void
unregister_serial
(
int
line
);
...
...
include/linux/serial_reg.h
View file @
5d278332
...
...
@@ -21,6 +21,8 @@
#define UART_IER 1
/* Out: Interrupt Enable Register */
#define UART_IIR 2
/* In: Interrupt ID Register */
#define UART_FCR 2
/* Out: FIFO Control Register */
#define UART_EFR 2
/* I/O: Extended Features Register */
/* (DLAB=1, 16C660 only) */
#define UART_LCR 3
/* Out: Line Control Register */
#define UART_MCR 4
/* Out: Modem Control Register */
#define UART_LSR 5
/* In: Line Status Register */
...
...
@@ -29,6 +31,7 @@
/*
* These are the definitions for the FIFO Control Register
* (16650 only)
*/
#define UART_FCR_ENABLE_FIFO 0x01
/* Enable the FIFO */
#define UART_FCR_CLEAR_RCVR 0x02
/* Clear the RCVR FIFO */
...
...
@@ -39,6 +42,15 @@
#define UART_FCR_TRIGGER_4 0x40
/* Mask for trigger set at 4 */
#define UART_FCR_TRIGGER_8 0x80
/* Mask for trigger set at 8 */
#define UART_FCR_TRIGGER_14 0xC0
/* Mask for trigger set at 14 */
/* 16650 redefinitions */
#define UART_FCR6_R_TRIGGER_8 0x00
/* Mask for receive trigger set at 1 */
#define UART_FCR6_R_TRIGGER_16 0x40
/* Mask for receive trigger set at 4 */
#define UART_FCR6_R_TRIGGER_24 0x80
/* Mask for receive trigger set at 8 */
#define UART_FCR6_R_TRIGGER_28 0xC0
/* Mask for receive trigger set at 14 */
#define UART_FCR6_T_TRIGGER_16 0x00
/* Mask for transmit trigger set at 16 */
#define UART_FCR6_T_TRIGGER_8 0x10
/* Mask for transmit trigger set at 8 */
#define UART_FCR6_T_TRIGGER_24 0x20
/* Mask for transmit trigger set at 24 */
#define UART_FCR6_T_TRIGGER_30 0x30
/* Mask for transmit trigger set at 30 */
/*
* These are the definitions for the Line Control Register
...
...
@@ -109,5 +121,17 @@
#define UART_MSR_DCTS 0x01
/* Delta CTS */
#define UART_MSR_ANY_DELTA 0x0F
/* Any of the delta bits! */
/*
* These are the definitions for the Extended Features Register
* (StarTech 16C660 only, when DLAB=1)
*/
#define UART_EFR_CTS 0x80
/* CTS flow control */
#define UART_EFR_RTS 0x40
/* RTS flow control */
#define UART_EFR_SCD 0x20
/* Special character detect */
#define UART_EFR_ENI 0x10
/* Enhanced Interrupt */
/*
* the low four bits control software flow control
*/
#endif
/* _LINUX_SERIAL_REG_H */
include/linux/sys.h
View file @
5d278332
...
...
@@ -6,11 +6,6 @@
*/
#define NR_syscalls 256
/*
* These are system calls with the same entry-point
*/
#define _sys_clone _sys_fork
/*
* These are system calls that will be removed at some time
* due to newer versions existing..
...
...
include/linux/termios.h
View file @
5d278332
...
...
@@ -54,6 +54,8 @@
#define TIOCSLCKTRMIOS 0x5457
#define TIOCSERGSTRUCT 0x5458
/* For debugging only */
#define TIOCSERGETLSR 0x5459
/* Get line status register */
#define TIOCSERGETMULTI 0x545A
/* Get multiport config */
#define TIOCSERSETMULTI 0x545B
/* Set multiport config */
/* Used for packet mode */
#define TIOCPKT_DATA 0
...
...
@@ -193,6 +195,7 @@ struct termios {
#define CBAUDEX 0010000
#define B57600 0010001
#define B115200 0010002
#define B230400 0010003
#define CIBAUD 002003600000
/* input baud rate (not used) */
#define CRTSCTS 020000000000
/* flow control */
...
...
include/linux/tty.h
View file @
5d278332
...
...
@@ -222,6 +222,7 @@ struct tty_struct {
*/
unsigned
int
column
;
unsigned
char
lnext
:
1
,
erasing
:
1
,
raw
:
1
,
real_raw
:
1
,
icanon
:
1
;
unsigned
char
closing
:
1
;
unsigned
short
minimum_to_wake
;
unsigned
overrun_time
;
int
num_overrun
;
...
...
ipc/shm.c
View file @
5d278332
#define THREE_LEVEL
/*
* linux/ipc/shm.c
* Copyright (C) 1992, 1993 Krishna Balasubramanian
...
...
@@ -20,7 +21,7 @@ extern int ipcperms (struct ipc_perm *ipcp, short shmflg);
extern
unsigned
int
get_swap_page
(
void
);
static
int
findkey
(
key_t
key
);
static
int
newseg
(
key_t
key
,
int
shmflg
,
int
size
);
static
int
shm_map
(
struct
vm_area_struct
*
shmd
,
int
remap
);
static
int
shm_map
(
struct
vm_area_struct
*
shmd
);
static
void
killseg
(
int
id
);
static
void
shm_open
(
struct
vm_area_struct
*
shmd
);
static
void
shm_close
(
struct
vm_area_struct
*
shmd
);
...
...
@@ -411,34 +412,16 @@ static inline void remove_attach (struct shmid_ds * shp, struct vm_area_struct *
}
/*
*
check range is unmapped,
ensure page tables exist
* ensure page tables exist
* mark page table entries with shm_sgn.
* if remap != 0 the range is remapped.
*/
static
int
shm_map
(
struct
vm_area_struct
*
shmd
,
int
remap
)
static
int
shm_map
(
struct
vm_area_struct
*
shmd
)
{
pgd_t
*
page_dir
;
pmd_t
*
page_middle
;
pte_t
*
page_table
;
unsigned
long
tmp
,
shm_sgn
;
/* check that the range is unmapped */
if
(
!
remap
)
for
(
tmp
=
shmd
->
vm_start
;
tmp
<
shmd
->
vm_end
;
tmp
+=
PAGE_SIZE
)
{
page_dir
=
PAGE_DIR_OFFSET
(
shmd
->
vm_task
,
tmp
);
if
(
pgd_none
(
*
page_dir
))
continue
;
if
(
pgd_bad
(
*
page_dir
))
{
printk
(
"bad ipc page directory entry %08lx
\n
"
,
pgd_val
(
*
page_dir
));
pgd_clear
(
page_dir
);
continue
;
}
page_table
=
(
pte_t
*
)
pgd_page
(
*
page_dir
);
page_table
+=
((
tmp
>>
PAGE_SHIFT
)
&
(
PTRS_PER_PAGE
-
1
));
if
(
!
pte_none
(
*
page_table
))
{
/* printk("shmat() -> EINVAL because address 0x%lx is already mapped.\n",tmp); */
return
-
EINVAL
;
}
}
int
error
;
/* clear old mappings */
do_munmap
(
shmd
->
vm_start
,
shmd
->
vm_end
-
shmd
->
vm_start
);
...
...
@@ -447,35 +430,17 @@ static int shm_map (struct vm_area_struct *shmd, int remap)
insert_vm_struct
(
current
,
shmd
);
merge_segments
(
current
,
shmd
->
vm_start
,
shmd
->
vm_end
);
/* check that the range has page_tables */
for
(
tmp
=
shmd
->
vm_start
;
tmp
<
shmd
->
vm_end
;
tmp
+=
PAGE_SIZE
)
{
page_dir
=
PAGE_DIR_OFFSET
(
shmd
->
vm_task
,
tmp
);
if
(
!
pgd_none
(
*
page_dir
))
{
page_table
=
(
pte_t
*
)
pgd_page
(
*
page_dir
);
page_table
+=
((
tmp
>>
PAGE_SHIFT
)
&
(
PTRS_PER_PAGE
-
1
));
if
(
!
pte_none
(
*
page_table
))
{
if
(
pte_present
(
*
page_table
))
{
--
current
->
mm
->
rss
;
free_page
(
pte_page
(
*
page_table
));
}
else
swap_free
(
pte_val
(
*
page_table
));
pte_clear
(
page_table
);
}
}
else
{
if
(
!
(
page_table
=
(
pte_t
*
)
get_free_page
(
GFP_KERNEL
)))
return
-
ENOMEM
;
pgd_set
(
page_dir
,
page_table
);
tmp
|=
(
PGDIR_SIZE
-
PAGE_SIZE
);
}
}
/* map page range */
shm_sgn
=
shmd
->
vm_pte
+
((
shmd
->
vm_offset
>>
PAGE_SHIFT
)
<<
SHM_IDX_SHIFT
);
for
(
tmp
=
shmd
->
vm_start
;
tmp
<
shmd
->
vm_end
;
tmp
+=
PAGE_SIZE
,
shm_sgn
+=
(
1
<<
SHM_IDX_SHIFT
))
{
page_dir
=
PAGE_DIR_OFFSET
(
shmd
->
vm_task
,
tmp
);
page_table
=
(
pte_t
*
)
pgd_page
(
*
page_dir
);
page_table
+=
(
tmp
>>
PAGE_SHIFT
)
&
(
PTRS_PER_PAGE
-
1
);
page_dir
=
pgd_offset
(
shmd
->
vm_task
,
tmp
);
page_middle
=
pmd_alloc
(
page_dir
,
tmp
);
if
(
!
page_middle
)
break
;
page_table
=
pte_alloc
(
page_middle
,
tmp
);
if
(
!
page_table
)
break
;
pte_val
(
*
page_table
)
=
shm_sgn
;
}
invalidate
();
...
...
@@ -553,7 +518,7 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
shmd
->
vm_ops
=
&
shm_vm_ops
;
shp
->
shm_nattch
++
;
/* prevent destruction */
if
((
err
=
shm_map
(
shmd
,
shmflg
&
SHM_REMAP
)))
{
if
((
err
=
shm_map
(
shmd
)))
{
if
(
--
shp
->
shm_nattch
<=
0
&&
shp
->
shm_perm
.
mode
&
SHM_DEST
)
killseg
(
id
);
kfree
(
shmd
);
...
...
@@ -749,6 +714,7 @@ int shm_swap (int prio)
for
(
shmd
=
shp
->
attaches
;
;
)
{
do
{
pgd_t
*
page_dir
;
pmd_t
*
page_middle
;
pte_t
*
page_table
,
pte
;
unsigned
long
tmp
;
...
...
@@ -759,15 +725,21 @@ int shm_swap (int prio)
tmp
=
shmd
->
vm_start
+
(
idx
<<
PAGE_SHIFT
)
-
shmd
->
vm_offset
;
if
(
!
(
tmp
>=
shmd
->
vm_start
&&
tmp
<
shmd
->
vm_end
))
continue
;
page_dir
=
PAGE_DIR_OFFSET
(
shmd
->
vm_task
,
tmp
);
page_dir
=
pgd_offset
(
shmd
->
vm_task
,
tmp
);
if
(
pgd_none
(
*
page_dir
)
||
pgd_bad
(
*
page_dir
))
{
printk
(
"shm_swap: bad pgtbl! id=%ld start=%lx idx=%ld
\n
"
,
id
,
shmd
->
vm_start
,
idx
);
pgd_clear
(
page_dir
);
continue
;
}
page_table
=
(
pte_t
*
)
pgd_page
(
*
page_dir
);
page_table
+=
((
tmp
>>
PAGE_SHIFT
)
&
(
PTRS_PER_PAGE
-
1
));
page_middle
=
pmd_offset
(
page_dir
,
tmp
);
if
(
pmd_none
(
*
page_middle
)
||
pmd_bad
(
*
page_middle
))
{
printk
(
"shm_swap: bad pgmid! id=%ld start=%lx idx=%ld
\n
"
,
id
,
shmd
->
vm_start
,
idx
);
pmd_clear
(
page_middle
);
continue
;
}
page_table
=
pte_offset
(
page_middle
,
tmp
);
pte
=
*
page_table
;
if
(
!
pte_present
(
pte
))
continue
;
...
...
@@ -779,7 +751,8 @@ int shm_swap (int prio)
printk
(
"shm_swap_out: page and pte mismatch
\n
"
);
pte_val
(
*
page_table
)
=
shmd
->
vm_pte
|
idx
<<
SHM_IDX_SHIFT
;
mem_map
[
MAP_NR
(
pte_page
(
pte
))]
--
;
shmd
->
vm_task
->
mm
->
rss
--
;
if
(
shmd
->
vm_task
->
mm
->
rss
>
0
)
shmd
->
vm_task
->
mm
->
rss
--
;
invalid
++
;
/* continue looping through circular list */
}
while
(
0
);
...
...
kernel/fork.c
View file @
5d278332
...
...
@@ -163,12 +163,11 @@ static void copy_fs(unsigned long clone_flags, struct task_struct * p)
* information (task[nr]) and sets up the necessary registers. It
* also copies the data segment in its entirety.
*/
asmlinkage
int
sys_fork
(
struct
pt_regs
regs
)
int
do_fork
(
unsigned
long
clone_flags
,
unsigned
long
usp
,
struct
pt_regs
*
regs
)
{
int
nr
;
struct
task_struct
*
p
;
unsigned
long
new_stack
;
unsigned
long
clone_flags
=
COPYVM
|
SIGCHLD
;
struct
task_struct
*
p
;
if
(
!
(
p
=
(
struct
task_struct
*
)
__get_free_page
(
GFP_KERNEL
)))
goto
bad_fork
;
...
...
@@ -206,7 +205,7 @@ asmlinkage int sys_fork(struct pt_regs regs)
task
[
nr
]
=
p
;
/* copy all the process information */
c
lone_flags
=
copy_thread
(
nr
,
COPYVM
|
SIGCHLD
,
p
,
&
regs
);
c
opy_thread
(
nr
,
clone_flags
,
usp
,
p
,
regs
);
if
(
copy_mm
(
clone_flags
,
p
))
goto
bad_fork_cleanup
;
p
->
semundo
=
NULL
;
...
...
kernel/sys.c
View file @
5d278332
...
...
@@ -517,6 +517,7 @@ asmlinkage int sys_setsid(void)
current
->
leader
=
1
;
current
->
session
=
current
->
pgrp
=
current
->
pid
;
current
->
tty
=
NULL
;
current
->
tty_old_pgrp
=
0
;
return
current
->
pgrp
;
}
...
...
mm/swap.c
View file @
5d278332
...
...
@@ -506,11 +506,10 @@ static int swap_out_process(struct task_struct * p)
static
int
swap_out
(
unsigned
int
priority
)
{
static
int
swap_task
;
int
loop
;
int
counter
=
NR_TASKS
*
2
>>
priority
;
int
loop
,
counter
;
struct
task_struct
*
p
;
counter
=
NR_TASKS
*
2
>>
priority
;
counter
=
2
*
NR_TASKS
>>
priority
;
for
(;
counter
>=
0
;
counter
--
,
swap_task
++
)
{
/*
* Check that swap_task is suitable for swapping. If not, look for
...
...
@@ -557,6 +556,15 @@ static int swap_out(unsigned int priority)
return
0
;
}
/*
* we keep on shrinking one resource until it's considered "too hard",
* and then switch to the next one (priority being an indication on how
* hard we should try with the resource).
*
* This should automatically find the resource that can most easily be
* free'd, so hopefully we'll get reasonable behaviour even under very
* different circumstances.
*/
static
int
try_to_free_page
(
int
priority
)
{
static
int
state
=
0
;
...
...
@@ -565,23 +573,19 @@ static int try_to_free_page(int priority)
switch
(
state
)
{
do
{
case
0
:
if
(
priority
!=
GFP_NOBUFFER
&&
shrink_buffers
(
i
))
{
state
=
1
;
if
(
priority
!=
GFP_NOBUFFER
&&
shrink_buffers
(
i
))
return
1
;
}
state
=
1
;
case
1
:
if
(
shm_swap
(
i
))
{
state
=
2
;
if
(
shm_swap
(
i
))
return
1
;
}
case
2
:
if
(
swap_out
(
i
))
{
state
=
0
;
state
=
2
;
default:
if
(
swap_out
(
i
))
return
1
;
}
state
=
0
;
}
while
(
--
i
);
}
state
=
2
;
return
0
;
}
...
...
net/inet/af_inet.c
View file @
5d278332
...
...
@@ -864,11 +864,13 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr,
{
/* should be below! */
if
(
sk2
->
num
!=
snum
)
continue
;
#if 0
if (sk2->dead)
{
destroy_sock(sk2);
goto outside_loop;
}
#endif
if
(
!
sk
->
reuse
)
{
sti
();
...
...
net/inet/tcp.c
View file @
5d278332
...
...
@@ -2769,9 +2769,9 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
newsk
->
linger
=
0
;
newsk
->
destroy
=
0
;
init_timer
(
&
newsk
->
timer
);
init_timer
(
&
newsk
->
retransmit_timer
);
newsk
->
timer
.
data
=
(
unsigned
long
)
newsk
;
newsk
->
timer
.
function
=
&
net_timer
;
init_timer
(
&
newsk
->
retransmit_timer
);
newsk
->
retransmit_timer
.
data
=
(
unsigned
long
)
newsk
;
newsk
->
retransmit_timer
.
function
=&
retransmit_timer
;
newsk
->
dummy_th
.
source
=
skb
->
h
.
th
->
dest
;
...
...
@@ -4393,7 +4393,9 @@ static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
tcp_set_state
(
sk
,
TCP_SYN_SENT
);
sk
->
rto
=
TCP_TIMEOUT_INIT
;
init_timer
(
&
sk
->
retransmit_timer
);
#if 0 /* we already did this */
init_timer(&sk->retransmit_timer);
#endif
sk
->
retransmit_timer
.
function
=&
retransmit_timer
;
sk
->
retransmit_timer
.
data
=
(
unsigned
long
)
sk
;
reset_xmit_timer
(
sk
,
TIME_WRITE
,
sk
->
rto
);
/* Timer for repeating the SYN until an answer */
...
...
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