Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
a6614639
Commit
a6614639
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 1.1.61
parent
ba97e35a
Changes
42
Hide whitespace changes
Inline
Side-by-side
Showing
42 changed files
with
2767 additions
and
399 deletions
+2767
-399
CREDITS
CREDITS
+1
-1
Makefile
Makefile
+1
-1
drivers/block/README.sbpcd
drivers/block/README.sbpcd
+66
-6
drivers/block/cdu31a.c
drivers/block/cdu31a.c
+1
-1
drivers/block/floppy.c
drivers/block/floppy.c
+7
-2
drivers/block/mcd.c
drivers/block/mcd.c
+0
-1
drivers/block/sbpcd.c
drivers/block/sbpcd.c
+28
-10
drivers/char/tpqic02.c
drivers/char/tpqic02.c
+30
-28
drivers/net/CONFIG
drivers/net/CONFIG
+6
-4
drivers/net/Makefile
drivers/net/Makefile
+5
-0
drivers/net/README.ewrk3
drivers/net/README.ewrk3
+43
-0
drivers/net/Space.c
drivers/net/Space.c
+4
-0
drivers/net/ewrk3.c
drivers/net/ewrk3.c
+1835
-0
drivers/net/ewrk3.h
drivers/net/ewrk3.h
+319
-0
fs/block_dev.c
fs/block_dev.c
+2
-2
fs/minix/inode.c
fs/minix/inode.c
+1
-0
fs/msdos/fat.c
fs/msdos/fat.c
+13
-16
fs/msdos/file.c
fs/msdos/file.c
+12
-10
fs/msdos/inode.c
fs/msdos/inode.c
+1
-14
fs/msdos/misc.c
fs/msdos/misc.c
+4
-4
fs/read_write.c
fs/read_write.c
+4
-1
fs/umsdos/inode.c
fs/umsdos/inode.c
+7
-0
fs/xiafs/bitmap.c
fs/xiafs/bitmap.c
+0
-1
include/linux/cdrom.h
include/linux/cdrom.h
+7
-1
include/linux/ipc.h
include/linux/ipc.h
+1
-1
include/linux/msdos_fs.h
include/linux/msdos_fs.h
+2
-6
include/linux/msg.h
include/linux/msg.h
+9
-11
include/linux/sched.h
include/linux/sched.h
+1
-1
include/linux/sem.h
include/linux/sem.h
+15
-14
include/linux/shm.h
include/linux/shm.h
+25
-25
ipc/msg.c
ipc/msg.c
+52
-31
ipc/sem.c
ipc/sem.c
+66
-61
ipc/shm.c
ipc/shm.c
+115
-100
ipc/util.c
ipc/util.c
+21
-12
kernel/exit.c
kernel/exit.c
+1
-1
kernel/ksyms.c
kernel/ksyms.c
+9
-11
mm/memory.c
mm/memory.c
+1
-1
net/inet/af_inet.c
net/inet/af_inet.c
+36
-9
net/inet/ip.c
net/inet/ip.c
+6
-7
net/inet/proc.c
net/inet/proc.c
+1
-1
net/inet/route.c
net/inet/route.c
+3
-3
net/inet/tcp.c
net/inet/tcp.c
+6
-1
No files found.
CREDITS
View file @
a6614639
...
@@ -64,7 +64,7 @@ S: 6369 BG Simpelveld
...
@@ -64,7 +64,7 @@ S: 6369 BG Simpelveld
S: The Netherlands
S: The Netherlands
N: Hennus Bergman
N: Hennus Bergman
E: hennus@sky.
nl.mugnet
.org [My uucp-fed Linux box at home]
E: hennus@sky.
ow
.org [My uucp-fed Linux box at home]
D: Author and maintainer of the QIC-02 tape driver
D: Author and maintainer of the QIC-02 tape driver
S: The Netherlands
S: The Netherlands
...
...
Makefile
View file @
a6614639
VERSION
=
1
VERSION
=
1
PATCHLEVEL
=
1
PATCHLEVEL
=
1
SUBLEVEL
=
6
0
SUBLEVEL
=
6
1
ARCH
=
i386
ARCH
=
i386
...
...
drivers/block/README.sbpcd
View file @
a6614639
This README belongs to release 2.
6
or newer of the SoundBlaster Pro
This README belongs to release 2.
7
or newer of the SoundBlaster Pro
(Matsushita, Kotobuki, Panasonic, CreativeLabs) CD-ROM driver for Linux.
(Matsushita, Kotobuki, Panasonic, CreativeLabs) CD-ROM driver for Linux.
The driver is able to drive the whole family of "traditional" IDE-style (that
The driver is able to drive the whole family of "traditional" IDE-style (that
...
@@ -6,6 +6,14 @@ has nothing to do with the new "Enhanced IDE" drive standard) Matsushita,
...
@@ -6,6 +6,14 @@ has nothing to do with the new "Enhanced IDE" drive standard) Matsushita,
Kotobuki, Panasonic drives, sometimes labelled as "CreativeLabs". The
Kotobuki, Panasonic drives, sometimes labelled as "CreativeLabs". The
well-known drives are CR-521, CR-522, CR-523, CR-562, CR-563.
well-known drives are CR-521, CR-522, CR-523, CR-562, CR-563.
There exists an "IBM External ISA CD-ROM Drive" which in fact is a CR-562
with a special controller board. This drive is supported (the interface is
of the "LaserMate" type), and it is possibly the best buy today (cheaper than
an internal drive, and you can use it as an internal, too - f.e. plug it into
a soundcard). If you own such a drive, please mail me the DOS driver (gzipped
and uuencoded) and the specifications (exact name, address range etc.) I still
have to confirm my opinion. ;-)
This driver is NOT for Mitsumi or Sony or Aztech or Philips or XXX drives.
This driver is NOT for Mitsumi or Sony or Aztech or Philips or XXX drives.
The matter that some other brand's drives work with newer sound card
The matter that some other brand's drives work with newer sound card
interfaces does NOT make the drives compatible. :-)
interfaces does NOT make the drives compatible. :-)
...
@@ -49,8 +57,8 @@ to change old drives to any ID, too. He writes in this sense:
...
@@ -49,8 +57,8 @@ to change old drives to any ID, too. He writes in this sense:
To use more than 4 drives (now that the single-speed CR-521's are as cheap as
To use more than 4 drives (now that the single-speed CR-521's are as cheap as
50$), you need a second interface card and you have to "duplicate" the driver.
50$), you need a second interface card and you have to "duplicate" the driver.
Just copy sbpcd.c into sbpcd2.c and so forth and change SBPCD_ISSUE
Just copy sbpcd.c into sbpcd2.c and so forth and change SBPCD_ISSUE
(at top
accordingly.
of sbpcd2.c)
accordingly.
The driver supports reading of data from the CD and playing of audio tracks.
The driver supports reading of data from the CD and playing of audio tracks.
The audio part should run with WorkMan, xcdplayer, with the "non-X11" products
The audio part should run with WorkMan, xcdplayer, with the "non-X11" products
...
@@ -72,9 +80,10 @@ the beginning of each single frame.
...
@@ -72,9 +80,10 @@ the beginning of each single frame.
The software interface possibly may change a bit the day the SCSI driver
The software interface possibly may change a bit the day the SCSI driver
supports it too.
supports it too.
MultiSession is supported, "ManySession" (not recommended, see below)
With the CR-562 and CR-563 drives, MultiSession is supported, "ManySession"
alternatively.
(not recommended, see below) alternatively.
Photo CDs work, too (even with my "old" CR-521).
Photo CDs work, too (the "old" drives like CR-521 can access only the first
session of a photoCD).
At ftp.gwdg.de:/pub/linux/hpcdtoppm/ is Hadmut Danisch's package to convert
At ftp.gwdg.de:/pub/linux/hpcdtoppm/ is Hadmut Danisch's package to convert
photo CD image files.
photo CD image files.
...
@@ -189,6 +198,57 @@ distribution) which MUST get handled with a block_size of 1024. Generally,
...
@@ -189,6 +198,57 @@ distribution) which MUST get handled with a block_size of 1024. Generally,
one can say all the CDs which hold files of the name YMTRANS.TBL are defective;
one can say all the CDs which hold files of the name YMTRANS.TBL are defective;
do not use block=2048 with those.
do not use block=2048 with those.
At the beginning of sbpcd.c, you will find some "#define"s (f.e. EJECT and
JUKEBOX). With that, you can configure the driver for some special things.
The following program disables the auto-eject feature during runtime:
/*=================== begin program ========================================*/
/*
* set the "eject" switch (enable/disable auto-ejecting)
*
* (c) 1994 Eberhard Moenkeberg <emoenke@gwdg.de>
* may be used & enhanced freely
*
* Disables or enables the auto-eject feature at run time.
* Works only if a CD is in the drive (just like the feature itself ;-)
* Useful for a "quiet" shutdown or for weird audio player programs.
*/
#define EJECT 0 /* 0: disable, 1: enable auto-ejecting */
#include <stdio.h>
#include <sys/ioctl.h>
#include <linux/cdrom.h>
static char arg=EJECT;
static int drive;
static int err;
main(int argc, char *argv[])
{
/*
* open /dev/cdrom
*/
drive=open("/dev/cdrom", 0);
if (drive<0)
{
fprintf(stderr, "can't open drive /dev/cdrom.\n");
exit (-1);
}
/*
* set EJECT_SW
*/
err=ioctl(drive, CDROMEJECT_SW, arg);
if (err!=0)
{
fprintf(stderr, "can't set EJECT_SW (error %d).\n", err);
exit (-1);
}
else
fprintf(stdout, "EJECT_SW set to %d\n", arg);
}
/*===================== end program ========================================*/
Auto-probing at boot time:
Auto-probing at boot time:
--------------------------
--------------------------
...
...
drivers/block/cdu31a.c
View file @
a6614639
...
@@ -2856,8 +2856,8 @@ cdu31a_init(unsigned long mem_start, unsigned long mem_end)
...
@@ -2856,8 +2856,8 @@ cdu31a_init(unsigned long mem_start, unsigned long mem_end)
{
{
if
(
request_irq
(
irq_used
,
cdu31a_interrupt
,
SA_INTERRUPT
,
"cdu31a"
))
if
(
request_irq
(
irq_used
,
cdu31a_interrupt
,
SA_INTERRUPT
,
"cdu31a"
))
{
{
irq_used
=
0
;
printk
(
"Unable to grab IRQ%d for the CDU31A driver
\n
"
,
irq_used
);
printk
(
"Unable to grab IRQ%d for the CDU31A driver
\n
"
,
irq_used
);
irq_used
=
0
;
}
}
}
}
...
...
drivers/block/floppy.c
View file @
a6614639
...
@@ -348,6 +348,7 @@ struct floppy_struct *current_type[N_DRIVE] = {
...
@@ -348,6 +348,7 @@ struct floppy_struct *current_type[N_DRIVE] = {
struct
floppy_struct
user_params
[
N_DRIVE
];
struct
floppy_struct
user_params
[
N_DRIVE
];
static
int
floppy_sizes
[
256
];
static
int
floppy_sizes
[
256
];
static
int
floppy_blocksizes
[
256
]
=
{
0
,
};
/*
/*
* The driver is trying to determine the correct media format
* The driver is trying to determine the correct media format
...
@@ -2848,7 +2849,7 @@ static int floppy_open(struct inode * inode, struct file * filp)
...
@@ -2848,7 +2849,7 @@ static int floppy_open(struct inode * inode, struct file * filp)
if
(
floppy_grab_irq_and_dma
())
if
(
floppy_grab_irq_and_dma
())
return
-
EBUSY
;
return
-
EBUSY
;
if
(
filp
->
f_flags
&
O_EXCL
)
if
(
filp
->
f_flags
&
O_EXCL
)
UDRS
->
fd_ref
=
-
1
;
UDRS
->
fd_ref
=
-
1
;
else
else
UDRS
->
fd_ref
++
;
UDRS
->
fd_ref
++
;
...
@@ -2956,7 +2957,10 @@ static int floppy_revalidate(dev_t dev)
...
@@ -2956,7 +2957,10 @@ static int floppy_revalidate(dev_t dev)
UDRS
->
generation
++
;
UDRS
->
generation
++
;
if
(
!
current_type
[
drive
]
&&
!
TYPE
(
dev
)){
if
(
!
current_type
[
drive
]
&&
!
TYPE
(
dev
)){
/* auto-sensing */
/* auto-sensing */
if
(
!
(
bh
=
getblk
(
dev
,
0
,
1024
))){
int
size
=
floppy_blocksizes
[
MINOR
(
dev
)];
if
(
!
size
)
size
=
1024
;
if
(
!
(
bh
=
getblk
(
dev
,
0
,
size
))){
redo_fd_request
();
redo_fd_request
();
return
1
;
return
1
;
}
}
...
@@ -3062,6 +3066,7 @@ void floppy_init(void)
...
@@ -3062,6 +3066,7 @@ void floppy_init(void)
floppy_sizes
[
i
]
=
MAX_DISK_SIZE
;
floppy_sizes
[
i
]
=
MAX_DISK_SIZE
;
blk_size
[
MAJOR_NR
]
=
floppy_sizes
;
blk_size
[
MAJOR_NR
]
=
floppy_sizes
;
blksize_size
[
MAJOR_NR
]
=
floppy_blocksizes
;
blk_dev
[
MAJOR_NR
].
request_fn
=
DEVICE_REQUEST
;
blk_dev
[
MAJOR_NR
].
request_fn
=
DEVICE_REQUEST
;
timer_table
[
FLOPPY_TIMER
].
fn
=
floppy_shutdown
;
timer_table
[
FLOPPY_TIMER
].
fn
=
floppy_shutdown
;
timer_active
&=
~
(
1
<<
FLOPPY_TIMER
);
timer_active
&=
~
(
1
<<
FLOPPY_TIMER
);
...
...
drivers/block/mcd.c
View file @
a6614639
...
@@ -1182,7 +1182,6 @@ mcd_init(unsigned long mem_start, unsigned long mem_end)
...
@@ -1182,7 +1182,6 @@ mcd_init(unsigned long mem_start, unsigned long mem_end)
mcd_invalidate_buffers
();
mcd_invalidate_buffers
();
mcdPresent
=
1
;
mcdPresent
=
1
;
printk
(
"
\n
"
);
return
mem_start
;
return
mem_start
;
}
}
...
...
drivers/block/sbpcd.c
View file @
a6614639
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
* and for "no-sound" interfaces like Lasermate and the
* and for "no-sound" interfaces like Lasermate and the
* Panasonic CI-101P.
* Panasonic CI-101P.
*
*
* NOTE: This is release 2.
6
.
* NOTE: This is release 2.
7
.
* It works with my SbPro & drive CR-521 V2.11 from 2/92
* It works with my SbPro & drive CR-521 V2.11 from 2/92
* and with the new CR-562-B V0.75 on a "naked" Panasonic
* and with the new CR-562-B V0.75 on a "naked" Panasonic
* CI-101P interface. And vice versa.
* CI-101P interface. And vice versa.
...
@@ -128,6 +128,10 @@
...
@@ -128,6 +128,10 @@
*
*
* 2.6 Nothing new.
* 2.6 Nothing new.
*
*
* 2.7 Added CDROMEJECT_SW ioctl to set the "EJECT" behavior on the fly:
* 0 disables, 1 enables auto-ejecting. Useful to keep the tray in
* during shutdown.
*
* TODO
* TODO
*
*
* disk change detection
* disk change detection
...
@@ -203,7 +207,7 @@
...
@@ -203,7 +207,7 @@
#include "blk.h"
#include "blk.h"
#define VERSION "2.
6
Eberhard Moenkeberg <emoenke@gwdg.de>"
#define VERSION "2.
7
Eberhard Moenkeberg <emoenke@gwdg.de>"
#define SBPCD_DEBUG
#define SBPCD_DEBUG
...
@@ -303,6 +307,9 @@ static int autoprobe[] =
...
@@ -303,6 +307,9 @@ static int autoprobe[] =
0x320
,
2
,
/* SPEA Media FX */
0x320
,
2
,
/* SPEA Media FX */
0x340
,
2
,
/* SPEA Media FX */
0x340
,
2
,
/* SPEA Media FX */
0x350
,
2
,
/* SPEA Media FX */
0x350
,
2
,
/* SPEA Media FX */
/* due to incomplete address decoding of the SbPro card, these must be last */
0x630
,
0
,
/* "sound card #9" (default) */
0x650
,
0
,
/* "sound card #9" */
#if 0
#if 0
/* some "hazardous" locations (ethernet cards) */
/* some "hazardous" locations (ethernet cards) */
0x330, 0, /* Lasermate, CI-101P, WDH-7001C */
0x330, 0, /* Lasermate, CI-101P, WDH-7001C */
...
@@ -310,9 +317,6 @@ static int autoprobe[] =
...
@@ -310,9 +317,6 @@ static int autoprobe[] =
0x370, 0, /* Lasermate, CI-101P */
0x370, 0, /* Lasermate, CI-101P */
0x290, 1, /* Soundblaster 16 */
0x290, 1, /* Soundblaster 16 */
0x310, 0, /* Lasermate, CI-101P, WDH-7001C */
0x310, 0, /* Lasermate, CI-101P, WDH-7001C */
/* excluded due to incomplete address decoding of the SbPro card */
0x630, 0, /* "sound card #9" (default) */
0x650, 0, /* "sound card #9" */
#endif
#endif
};
};
...
@@ -390,6 +394,7 @@ static int sbpcd_debug = (1<<DBG_INF) |
...
@@ -390,6 +394,7 @@ static int sbpcd_debug = (1<<DBG_INF) |
#else
#else
static
int
sbpcd_debug
=
(
1
<<
DBG_INF
)
|
static
int
sbpcd_debug
=
(
1
<<
DBG_INF
)
|
(
1
<<
DBG_TOC
)
|
(
1
<<
DBG_TOC
)
|
(
1
<<
DBG_MUL
)
|
(
1
<<
DBG_UPC
);
(
1
<<
DBG_UPC
);
#endif
#endif
#endif
#endif
...
@@ -481,6 +486,7 @@ static struct {
...
@@ -481,6 +486,7 @@ static struct {
char
drive_model
[
4
];
char
drive_model
[
4
];
char
firmware_version
[
4
];
char
firmware_version
[
4
];
char
f_eject
;
/* auto-eject flag: 0 or 1 */
u_char
*
sbp_buf
;
/* Pointer to internal data buffer,
u_char
*
sbp_buf
;
/* Pointer to internal data buffer,
space allocated during sbpcd_init() */
space allocated during sbpcd_init() */
int
sbp_first_frame
;
/* First frame in buffer */
int
sbp_first_frame
;
/* First frame in buffer */
...
@@ -2390,7 +2396,7 @@ static int sbp_status(void)
...
@@ -2390,7 +2396,7 @@ static int sbp_status(void)
/*==========================================================================*/
/*==========================================================================*/
/*==========================================================================*/
/*==========================================================================*/
/*
/*
* ioctl support
, adopted from scsi/sr_ioctl.c and mcd.c
* ioctl support
*/
*/
static
int
sbpcd_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
u_int
cmd
,
static
int
sbpcd_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
u_int
cmd
,
u_long
arg
)
u_long
arg
)
...
@@ -2583,6 +2589,12 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
...
@@ -2583,6 +2589,12 @@ static int sbpcd_ioctl(struct inode *inode, struct file *file, u_int cmd,
DriveStruct
[
d
].
audio_state
=
0
;
DriveStruct
[
d
].
audio_state
=
0
;
return
(
0
);
return
(
0
);
case
CDROMEJECT_SW
:
DPRINTF
((
DBG_IOC
,
"SBPCD: ioctl: CDROMEJECT_SW entered.
\n
"
));
if
(
!
new_drive
)
return
(
0
);
DriveStruct
[
d
].
f_eject
=
arg
;
return
(
0
);
case
CDROMVOLCTRL
:
/* Volume control */
case
CDROMVOLCTRL
:
/* Volume control */
DPRINTF
((
DBG_IOC
,
"SBPCD: ioctl: CDROMVOLCTRL entered.
\n
"
));
DPRINTF
((
DBG_IOC
,
"SBPCD: ioctl: CDROMVOLCTRL entered.
\n
"
));
st
=
verify_area
(
VERIFY_READ
,(
void
*
)
arg
,
sizeof
(
volctrl
));
st
=
verify_area
(
VERIFY_READ
,(
void
*
)
arg
,
sizeof
(
volctrl
));
...
@@ -2918,7 +2930,9 @@ static void DO_SBPCD_REQUEST(void)
...
@@ -2918,7 +2930,9 @@ static void DO_SBPCD_REQUEST(void)
}
}
DPRINTF
((
DBG_BSZ
,
"SBPCD: read sector %d (%d sectors)
\n
"
,
block
,
nsect
));
DPRINTF
((
DBG_BSZ
,
"SBPCD: read sector %d (%d sectors)
\n
"
,
block
,
nsect
));
#if 0
DPRINTF((DBG_MUL,"SBPCD: read LBA %d\n", block/4));
DPRINTF((DBG_MUL,"SBPCD: read LBA %d\n", block/4));
#endif
sbp_transfer
();
sbp_transfer
();
/* if we satisfied the request from the buffer, we're done. */
/* if we satisfied the request from the buffer, we're done. */
...
@@ -3007,7 +3021,7 @@ static void sbp_read_cmd(void)
...
@@ -3007,7 +3021,7 @@ static void sbp_read_cmd(void)
DPRINTF
((
DBG_MUL
,
"SBPCD: MultiSession: use %08X for %08X (msf)
\n
"
,
DPRINTF
((
DBG_MUL
,
"SBPCD: MultiSession: use %08X for %08X (msf)
\n
"
,
blk2msf
(
DriveStruct
[
d
].
lba_multi
+
16
),
blk2msf
(
DriveStruct
[
d
].
lba_multi
+
16
),
blk2msf
(
block
)));
blk2msf
(
block
)));
block
=
DriveStruct
[
d
].
lba_multi
+
16
;
block
=
DriveStruct
[
d
].
lba_multi
+
block
;
}
}
#endif MANY_SESSION
#endif MANY_SESSION
}
}
...
@@ -3323,9 +3337,7 @@ static void sbpcd_release(struct inode * ip, struct file * file)
...
@@ -3323,9 +3337,7 @@ static void sbpcd_release(struct inode * ip, struct file * file)
do
do
i
=
yy_LockDoor
(
0
);
i
=
yy_LockDoor
(
0
);
while
(
i
!=
0
);
while
(
i
!=
0
);
#if EJECT
if
(
DriveStruct
[
d
].
f_eject
)
yy_SpinDown
();
if
(
new_drive
)
yy_SpinDown
();
#endif
}
}
}
}
}
}
...
@@ -3550,6 +3562,12 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
...
@@ -3550,6 +3562,12 @@ unsigned long SBPCD_INIT(u_long mem_start, u_long mem_end)
DriveStruct
[
d
].
sbp_current
=
0
;
/* Frame being currently read */
DriveStruct
[
d
].
sbp_current
=
0
;
/* Frame being currently read */
DriveStruct
[
d
].
CD_changed
=
1
;
DriveStruct
[
d
].
CD_changed
=
1
;
DriveStruct
[
d
].
frame_size
=
CD_FRAMESIZE
;
DriveStruct
[
d
].
frame_size
=
CD_FRAMESIZE
;
#if EJECT
if
(
new_drive
)
DriveStruct
[
d
].
f_eject
=
1
;
else
DriveStruct
[
d
].
f_eject
=
0
;
#else
DriveStruct
[
d
].
f_eject
=
0
;
#endif
xx_ReadStatus
();
xx_ReadStatus
();
i
=
ResponseStatus
();
/* returns orig. status or p_busy_new */
i
=
ResponseStatus
();
/* returns orig. status or p_busy_new */
...
...
drivers/char/tpqic02.c
View file @
a6614639
/* $Id: tpqic02.c,v 0.4.1.
4 1994/07/21 02:15:45
root Exp root $
/* $Id: tpqic02.c,v 0.4.1.
5 1994/10/29 02:46:13
root Exp root $
*
*
* Driver for tape drive support for Linux-i386 1.1.
30
* Driver for tape drive support for Linux-i386 1.1.
58
*
*
* Copyright (c) 1992, 1993, 1994 by H. H. Bergman. All rights reserved.
* Copyright (c) 1992, 1993, 1994 by H. H. Bergman. All rights reserved.
* Current e-mail address: hennus@sky.nl.mugnet.org [This is a UUCP link.]
* Current e-mail address: hennus@sky.ow.org [This is a UUCP link.]
* Secondary e-mail address: csg279@wing.rug.nl [IP connected, but flaky]
* [If you are unable to reach me directly, try the TAPE mailing list
* [If you are unable to reach me directly, try the TAPE mailing list
* channel on linux-activists@niksula.hut.fi using "X-Mn-Key: TAPE" as
* channel on linux-activists@niksula.hut.fi using "X-Mn-Key: TAPE" as
* the first line in your message.]
* the first line in your message.]
...
@@ -35,6 +34,9 @@
...
@@ -35,6 +34,9 @@
* You are not allowed to change this line nor the text above.
* You are not allowed to change this line nor the text above.
*
*
* $Log: tpqic02.c,v $
* $Log: tpqic02.c,v $
* Revision 0.4.1.5 1994/10/29 02:46:13 root
* Minor cleanups.
*
* Revision 0.4.1.4 1994/07/21 02:15:45 root
* Revision 0.4.1.4 1994/07/21 02:15:45 root
* ifdef'd DDI. Exception masks.
* ifdef'd DDI. Exception masks.
*
*
...
@@ -191,10 +193,8 @@
...
@@ -191,10 +193,8 @@
* Also, be careful to avoid IO conflicts with other devices!
* Also, be careful to avoid IO conflicts with other devices!
*/
*/
#include <linux/
config
.h>
#include <linux/
autoconf
.h>
/* skip this driver if not required for this configuration */
#if CONFIG_QIC02_TAPE
/*
/*
#define TDEBUG
#define TDEBUG
...
@@ -233,8 +233,8 @@
...
@@ -233,8 +233,8 @@
*/
*/
#ifdef CONFIG_QIC02_DYNCONF
#ifdef CONFIG_QIC02_DYNCONF
/* This
may hold
the dynamic configuration info for the interface
/* This
holds
the dynamic configuration info for the interface
* card+drive info i
n future versions
.
* card+drive info i
f runtime configuration has been selected
.
*/
*/
struct
mtconfiginfo
qic02_tape_dynconf
=
{
0
,
};
/* user settable */
struct
mtconfiginfo
qic02_tape_dynconf
=
{
0
,
};
/* user settable */
struct
qic02_ccb
qic02_tape_ccb
=
{
0
,
};
/* private stuff */
struct
qic02_ccb
qic02_tape_ccb
=
{
0
,
};
/* private stuff */
...
@@ -256,8 +256,8 @@ static volatile struct mtget ioctl_status; /* current generic status */
...
@@ -256,8 +256,8 @@ static volatile struct mtget ioctl_status; /* current generic status */
static
volatile
struct
tpstatus
tperror
;
/* last drive status */
static
volatile
struct
tpstatus
tperror
;
/* last drive status */
static
char
rcs_revision
[]
=
"$Revision: 0.4.1.
4
$"
;
static
char
rcs_revision
[]
=
"$Revision: 0.4.1.
5
$"
;
static
char
rcs_date
[]
=
"$Date: 1994/
07/21 02:15:45
$"
;
static
char
rcs_date
[]
=
"$Date: 1994/
10/29 02:46:13
$"
;
/* Flag bits for status and outstanding requests.
/* Flag bits for status and outstanding requests.
* (Could all be put in one bit-field-struct.)
* (Could all be put in one bit-field-struct.)
...
@@ -285,7 +285,7 @@ static volatile unsigned long dma_bytes_done;
...
@@ -285,7 +285,7 @@ static volatile unsigned long dma_bytes_done;
static
volatile
unsigned
dma_mode
=
0
;
/* !=0 also means DMA in use */
static
volatile
unsigned
dma_mode
=
0
;
/* !=0 also means DMA in use */
static
flag
need_rewind
=
YES
;
static
flag
need_rewind
=
YES
;
static
dev_t
current_tape_dev
=
QIC02_TAPE_MAJOR
<<
8
;
static
dev_t
current_tape_dev
=
MKDEV
(
QIC02_TAPE_MAJOR
,
0
)
;
static
int
extra_blocks_left
=
BLOCKS_BEYOND_EW
;
static
int
extra_blocks_left
=
BLOCKS_BEYOND_EW
;
...
@@ -570,7 +570,9 @@ static void report_error(int s)
...
@@ -570,7 +570,9 @@ static void report_error(int s)
#endif
#endif
/* perform appropriate action for certain exceptions */
/* Perform appropriate action for certain exceptions.
* should return a value to indicate stop/continue (in case of bad blocks)
*/
static
void
handle_exception
(
int
exnr
,
int
exbits
)
static
void
handle_exception
(
int
exnr
,
int
exbits
)
{
{
if
(
exnr
==
EXC_NCART
)
{
if
(
exnr
==
EXC_NCART
)
{
...
@@ -1358,9 +1360,7 @@ static int do_ioctl_cmd(int cmd)
...
@@ -1358,9 +1360,7 @@ static int do_ioctl_cmd(int cmd)
return
do_qic_cmd
(
QCMD_REWIND
,
TIM_R
);
return
do_qic_cmd
(
QCMD_REWIND
,
TIM_R
);
case
MTOFFL
:
case
MTOFFL
:
tpqputs
(
TPQD_IOCTLS
,
"MTOFFL rewinding & going offline"
);
/*---*/
tpqputs
(
TPQD_IOCTLS
,
"MTOFFL rewinding & going offline"
);
/******* What exactly are we supposed to do, to take it offline????
*****/
/* Doing a drive select will clear (unlock) the current drive.
/* Doing a drive select will clear (unlock) the current drive.
* But that requires support for multiple drives and locking.
* But that requires support for multiple drives and locking.
*/
*/
...
@@ -1927,8 +1927,9 @@ static int qic02_tape_read(struct inode * inode, struct file * filp, char * buf,
...
@@ -1927,8 +1927,9 @@ static int qic02_tape_read(struct inode * inode, struct file * filp, char * buf,
}
}
if
(
TP_DIAGS
(
current_tape_dev
))
if
(
TP_DIAGS
(
current_tape_dev
))
/* can't print a ``long long'' (for filp->f_pos), so chop it */
printk
(
TPQIC02_NAME
": request READ, minor=%x, buf=%p, count=%x, pos=%lx, flags=%x
\n
"
,
printk
(
TPQIC02_NAME
": request READ, minor=%x, buf=%p, count=%x, pos=%lx, flags=%x
\n
"
,
MINOR
(
dev
),
buf
,
count
,
filp
->
f_pos
,
flags
);
MINOR
(
dev
),
buf
,
count
,
(
unsigned
long
)
filp
->
f_pos
,
flags
);
if
(
count
%
TAPE_BLKSIZE
)
{
/* Only allow mod 512 bytes at a time. */
if
(
count
%
TAPE_BLKSIZE
)
{
/* Only allow mod 512 bytes at a time. */
tpqputs
(
TPQD_BLKSZ
,
"Wrong block size"
);
tpqputs
(
TPQD_BLKSZ
,
"Wrong block size"
);
...
@@ -2100,8 +2101,9 @@ static int qic02_tape_write(struct inode * inode, struct file * filp, char * buf
...
@@ -2100,8 +2101,9 @@ static int qic02_tape_write(struct inode * inode, struct file * filp, char * buf
}
}
if
(
TP_DIAGS
(
current_tape_dev
))
if
(
TP_DIAGS
(
current_tape_dev
))
/* can't print a ``long long'' (for filp->f_pos), so chop it */
printk
(
TPQIC02_NAME
": request WRITE, minor=%x, buf=%p, count=%x, pos=%lx, flags=%x
\n
"
,
printk
(
TPQIC02_NAME
": request WRITE, minor=%x, buf=%p, count=%x, pos=%lx, flags=%x
\n
"
,
MINOR
(
dev
),
buf
,
count
,
filp
->
f_pos
,
flags
);
MINOR
(
dev
),
buf
,
count
,
(
unsigned
long
)
filp
->
f_pos
,
flags
);
if
(
count
%
TAPE_BLKSIZE
)
{
/* only allow mod 512 bytes at a time */
if
(
count
%
TAPE_BLKSIZE
)
{
/* only allow mod 512 bytes at a time */
tpqputs
(
TPQD_BLKSZ
,
"Wrong block size"
);
tpqputs
(
TPQD_BLKSZ
,
"Wrong block size"
);
...
@@ -2587,7 +2589,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
...
@@ -2587,7 +2589,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
if
(
!
suser
())
if
(
!
suser
())
return
-
EPERM
;
return
-
EPERM
;
verify_area
(
VERIFY_READ
,
(
int
*
)
ioarg
,
sizeof
(
int
));
verify_area
(
VERIFY_READ
,
(
int
*
)
ioarg
,
sizeof
(
int
));
c
=
get_
fs
_long
((
int
*
)
ioarg
);
c
=
get_
user
_long
((
int
*
)
ioarg
);
if
(
c
==
0
)
{
if
(
c
==
0
)
{
QIC02_TAPE_DEBUG
=
0
;
QIC02_TAPE_DEBUG
=
0
;
return
0
;
return
0
;
...
@@ -2619,7 +2621,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
...
@@ -2619,7 +2621,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
stp
=
(
char
*
)
&
qic02_tape_dynconf
;
stp
=
(
char
*
)
&
qic02_tape_dynconf
;
argp
=
(
char
*
)
ioarg
;
argp
=
(
char
*
)
ioarg
;
for
(
i
=
0
;
i
<
sizeof
(
qic02_tape_dynconf
);
i
++
)
for
(
i
=
0
;
i
<
sizeof
(
qic02_tape_dynconf
);
i
++
)
put_
fs
_byte
(
*
stp
++
,
argp
++
);
put_
user
_byte
(
*
stp
++
,
argp
++
);
return
0
;
return
0
;
}
else
if
(
c
==
(
MTIOCSETCONFIG
&
IOCCMD_MASK
))
{
}
else
if
(
c
==
(
MTIOCSETCONFIG
&
IOCCMD_MASK
))
{
...
@@ -2646,7 +2648,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
...
@@ -2646,7 +2648,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
stp
=
(
char
*
)
&
qic02_tape_dynconf
;
stp
=
(
char
*
)
&
qic02_tape_dynconf
;
argp
=
(
char
*
)
ioarg
;
argp
=
(
char
*
)
ioarg
;
for
(
i
=
0
;
i
<
sizeof
(
qic02_tape_dynconf
);
i
++
)
for
(
i
=
0
;
i
<
sizeof
(
qic02_tape_dynconf
);
i
++
)
*
stp
++
=
get_
fs
_byte
(
argp
++
);
*
stp
++
=
get_
user
_byte
(
argp
++
);
if
(
status_zombie
==
NO
)
if
(
status_zombie
==
NO
)
qic02_release_resources
();
/* and go zombie */
qic02_release_resources
();
/* and go zombie */
if
(
update_ifc_masks
(
qic02_tape_dynconf
.
ifc_type
))
if
(
update_ifc_masks
(
qic02_tape_dynconf
.
ifc_type
))
...
@@ -2678,7 +2680,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
...
@@ -2678,7 +2680,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
stp
=
(
char
*
)
&
operation
;
stp
=
(
char
*
)
&
operation
;
argp
=
(
char
*
)
ioarg
;
argp
=
(
char
*
)
ioarg
;
for
(
i
=
0
;
i
<
sizeof
(
operation
);
i
++
)
for
(
i
=
0
;
i
<
sizeof
(
operation
);
i
++
)
*
stp
++
=
get_
fs
_byte
(
argp
++
);
*
stp
++
=
get_
user
_byte
(
argp
++
);
/* ---note: mt_count is signed, negative seeks must be
/* ---note: mt_count is signed, negative seeks must be
* --- translated to seeks in opposite direction!
* --- translated to seeks in opposite direction!
...
@@ -2740,7 +2742,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
...
@@ -2740,7 +2742,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
stp
=
(
char
*
)
&
ioctl_status
;
stp
=
(
char
*
)
&
ioctl_status
;
argp
=
(
char
*
)
ioarg
;
argp
=
(
char
*
)
ioarg
;
for
(
i
=
0
;
i
<
sizeof
(
ioctl_status
);
i
++
)
for
(
i
=
0
;
i
<
sizeof
(
ioctl_status
);
i
++
)
put_
fs
_byte
(
*
stp
++
,
argp
++
);
put_
user
_byte
(
*
stp
++
,
argp
++
);
return
0
;
return
0
;
...
@@ -2773,7 +2775,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
...
@@ -2773,7 +2775,7 @@ static int qic02_tape_ioctl(struct inode * inode, struct file * filp,
stp
=
(
char
*
)
&
ioctl_tell
;
stp
=
(
char
*
)
&
ioctl_tell
;
argp
=
(
char
*
)
ioarg
;
argp
=
(
char
*
)
ioarg
;
for
(
i
=
0
;
i
<
sizeof
(
ioctl_tell
);
i
++
)
for
(
i
=
0
;
i
<
sizeof
(
ioctl_tell
);
i
++
)
put_
fs
_byte
(
*
stp
++
,
argp
++
);
put_
user
_byte
(
*
stp
++
,
argp
++
);
return
0
;
return
0
;
}
else
}
else
...
@@ -2793,7 +2795,10 @@ static struct file_operations qic02_tape_fops = {
...
@@ -2793,7 +2795,10 @@ static struct file_operations qic02_tape_fops = {
NULL
,
/* mmap not allowed */
NULL
,
/* mmap not allowed */
qic02_tape_open
,
/* open */
qic02_tape_open
,
/* open */
qic02_tape_release
,
/* release */
qic02_tape_release
,
/* release */
NULL
/* fsync */
NULL
,
/* fsync */
NULL
,
/* fasync */
NULL
,
/* check_media_change */
NULL
/* revalidate */
};
};
/* align `a' at `size' bytes. `size' must be a power of 2 */
/* align `a' at `size' bytes. `size' must be a power of 2 */
...
@@ -2870,7 +2875,6 @@ static int qic02_get_resources(void)
...
@@ -2870,7 +2875,6 @@ static int qic02_get_resources(void)
/* init() is called from chr_dev_init() in drivers/char/mem.c */
long
qic02_tape_init
(
long
kmem_start
)
long
qic02_tape_init
(
long
kmem_start
)
/* Shouldn't this be a caddr_t ? */
/* Shouldn't this be a caddr_t ? */
{
{
...
@@ -2969,5 +2973,3 @@ long qic02_tape_init(long kmem_start)
...
@@ -2969,5 +2973,3 @@ long qic02_tape_init(long kmem_start)
return
kmem_start
;
return
kmem_start
;
}
/* qic02_tape_init */
}
/* qic02_tape_init */
#endif
/* CONFIG_QIC02_TAPE */
drivers/net/CONFIG
View file @
a6614639
...
@@ -34,9 +34,10 @@
...
@@ -34,9 +34,10 @@
# DE620_IO The DE620 I/O-port address (0x378 == default)
# DE620_IO The DE620 I/O-port address (0x378 == default)
# DE620_IRQ The DE620 IRQ number to use (IRQ7 == default)
# DE620_IRQ The DE620 IRQ number to use (IRQ7 == default)
# DE620_DEBUG Enable or disable DE600 debugging (default off)
# DE620_DEBUG Enable or disable DE600 debugging (default off)
# DEPCA The DIGITAL series of AT Ethernet Cards (DE100, DE200)
# DEPCA The DIGITAL series of LANCE based Ethernet Cards
# DEPCA_IRQ Set the desired IRQ (=0, for autoprobe)
# (DEPCA, DE100, DE200/1/2, DE210, DE422 (EISA))
# DEPCA_DEBUG Set the desired debug level
# EWRK3 The DIGITAL series of AT Ethernet Cards (DE203/4/5)
# EWRK3_DEBUG Set the desired debug level
#
#
# The following options exist, but cannot be set in this file.
# The following options exist, but cannot be set in this file.
...
@@ -57,4 +58,5 @@ EL2_OPTS = #-DEL2_AUI
...
@@ -57,4 +58,5 @@ EL2_OPTS = #-DEL2_AUI
NE_OPTS =
NE_OPTS =
HP_OPTS =
HP_OPTS =
PLIP_OPTS =
PLIP_OPTS =
DEPCA_OPTS = -DDEPCA_IRQ=0 -DDEPCA_DEBUG=1
DEPCA_OPTS = -DDEPCA_DEBUG=1
EWRK3_OPTS = -DEWRK3_DEBUG=1
drivers/net/Makefile
View file @
a6614639
...
@@ -142,6 +142,11 @@ NETDRV_OBJS := $(NETDRV_OBJS) depca.o
...
@@ -142,6 +142,11 @@ NETDRV_OBJS := $(NETDRV_OBJS) depca.o
depca.o
:
depca.c CONFIG
depca.o
:
depca.c CONFIG
$(CC)
$(CPPFLAGS)
$(CFLAGS)
$(DEPCA_OPTS)
-c
$<
$(CC)
$(CPPFLAGS)
$(CFLAGS)
$(DEPCA_OPTS)
-c
$<
endif
endif
ifdef
CONFIG_EWRK3
NETDRV_OBJS
:=
$(NETDRV_OBJS)
ewrk3.o
ewrk3.o
:
ewrk3.c CONFIG
$(CC)
$(CPPFLAGS)
$(CFLAGS)
$(EWRK3_OPTS)
-c
$<
endif
ifdef
CONFIG_ATP
ifdef
CONFIG_ATP
NETDRV_OBJS
:=
$(NETDRV_OBJS)
atp.o
NETDRV_OBJS
:=
$(NETDRV_OBJS)
atp.o
endif
endif
...
...
drivers/net/README.ewrk3
0 → 100644
View file @
a6614639
The EtherWORKS 3 driver in this distribution is designed to work with all
kernels > 1.1.33 (approx) and includes tools in the 'ewrk3tools'
subdirectory to allow set up of the card, similar to the MSDOS
'NICSETUP.EXE' tools provided on the DOS drivers disk (type 'make' in that
subdirectory to make the tools).
The supported cards are DE203, DE204 and DE205. All other cards are NOT
supported - refer to the depca files for running the LANCE based network
cards from Digital.
The ability to load this driver as a loadable module has been included and
used extensively during the driver development (to save those long reboot
sequences). To utilise this ability, you have to do 8 things:
0) have a copy of the loadable modules code installed on your system.
1) copy ewrk3.c from the /linux/drivers/net directory to your favourite
temporary directory.
2) edit the source code near line 1750 to reflect the I/O address and
IRQ you're using.
3) compile ewrk3.c, but include -DMODULE in the command line to ensure
that the correct bits are compiled (see end of source code).
4) if you are wanting to add a new card, goto 5. Otherwise, recompile a
kernel with the ewrk3 configuration turned off and reboot.
5) insmod ewrk3.o
6) run the net startup bits for your new eth?? interface manually
(usually /etc/rc.inet[12] at boot time).
7) enjoy!
Note that autoprobing is not allowed in loadable modules - the system is
already up and running and you're messing with interrupts.
To unload a module, turn off the associated interface
'ifconfig eth?? down' then 'rmmod ewrk3'.
The performance we've achieved so far has been measured through the 'ttcp'
tool at 975kB/s. This measures the total tcp stack performance which
includes the card, so don't expect to get much nearer the 1.25MB/s
theoretical ethernet rate.
Enjoy!
Dave
drivers/net/Space.c
View file @
a6614639
...
@@ -49,6 +49,7 @@ extern int el3_probe(struct device *);
...
@@ -49,6 +49,7 @@ extern int el3_probe(struct device *);
extern
int
at1500_probe
(
struct
device
*
);
extern
int
at1500_probe
(
struct
device
*
);
extern
int
at1700_probe
(
struct
device
*
);
extern
int
at1700_probe
(
struct
device
*
);
extern
int
depca_probe
(
struct
device
*
);
extern
int
depca_probe
(
struct
device
*
);
extern
int
ewrk3_probe
(
struct
device
*
);
extern
int
el1_probe
(
struct
device
*
);
extern
int
el1_probe
(
struct
device
*
);
extern
int
el16_probe
(
struct
device
*
);
extern
int
el16_probe
(
struct
device
*
);
extern
int
elplus_probe
(
struct
device
*
);
extern
int
elplus_probe
(
struct
device
*
);
...
@@ -108,6 +109,9 @@ ethif_probe(struct device *dev)
...
@@ -108,6 +109,9 @@ ethif_probe(struct device *dev)
#ifdef CONFIG_DEPCA
/* DEC DEPCA */
#ifdef CONFIG_DEPCA
/* DEC DEPCA */
&&
depca_probe
(
dev
)
&&
depca_probe
(
dev
)
#endif
#endif
#ifdef CONFIG_EWRK3
/* DEC EtherWORKS 3 */
&&
ewrk3_probe
(
dev
)
#endif
#ifdef CONFIG_EL1
/* 3c501 */
#ifdef CONFIG_EL1
/* 3c501 */
&&
el1_probe
(
dev
)
&&
el1_probe
(
dev
)
#endif
#endif
...
...
drivers/net/ewrk3.c
0 → 100644
View file @
a6614639
/* ewrk3.c: A DIGITAL EtherWORKS 3 ethernet driver for linux.
Written 1994 by David C. Davies.
Copyright 1994 Digital Equipment Corporation.
This software may be used and distributed according to the terms of
the GNU Public License, incorporated herein by reference.
This driver is written for the Digital Equipment Corporation series
of EtherWORKS ethernet cards:
DE203 Turbo (BNC)
DE204 Turbo (TP)
DE205 Turbo (TP BNC)
The driver has been tested on a relatively busy network using the DE205
card and benchmarked with 'ttcp': it transferred 16M of data at 975kB/s
(7.8Mb/s) to a DECstation 5000/200.
The author may be reached as davies@wanton.lkg.dec.com or Digital
Equipment Corporation, 550 King Street, Littleton MA 01460.
=========================================================================
This driver has been written substantially from scratch, although its
inheritance of style and stack interface from 'depca.c' and in turn from
Donald Becker's 'lance.c' should be obvious.
The DE203/4/5 boards all use a new proprietary chip in place of the
LANCE chip used in prior cards (DEPCA, DE100, DE200/1/2, DE210, DE422).
Use the depca.c driver in the standard distribution for the LANCE based
cards from DIGITAL; this driver will not work with them.
The DE203/4/5 cards have 2 main modes: shared memory and I/O only. I/O
only makes all the card accesses through I/O transactions and no high
(shared) memory is used. This mode provides a >48% performance penalty
and is deprecated in this driver, although allowed to provide initial
setup when hardstrapped.
The shared memory mode comes in 3 flavours: 2kB, 32kB and 64kB. There is
no point in using any mode other than the 2kB mode - their performances
are virtually identical, although the driver has been tested in the 2kB
and 32kB modes. I would suggest you uncomment the line:
FORCE_2K_MODE;
to allow the driver to configure the card as a 2kB card at your current
base address, thus leaving more room to clutter your system box with
other memory hungry boards.
Upto 21 ISA and 7 EISA cards can be supported under this driver, limited
primarily by the available IRQ lines. I have checked different
configurations of multiple depca cards and ewrk3 cards and have not
found a problem yet (provided you have at least depca.c v0.38) ...
The board IRQ setting must be at an unused IRQ which is auto-probed
using Donald Becker's autoprobe routines. All these cards are at
{5,10,11,15}.
No 16MB memory limitation should exist with this driver as DMA is not
used and the common memory area is in low memory on the network card (my
current system has 20MB and I've not had problems yet).
The ability to load this driver as a loadable module has been included
and used extensively during the driver development (to save those long
reboot sequences). To utilise this ability, you have to do 8 things:
0) have a copy of the loadable modules code installed on your system.
1) copy ewrk3.c from the /linux/drivers/net directory to your favourite
temporary directory.
2) edit the source code near line 1340 to reflect the I/O address and
IRQ you're using.
3) compile ewrk3.c, but include -DMODULE in the command line to ensure
that the correct bits are compiled (see end of source code).
4) if you are wanting to add a new card, goto 5. Otherwise, recompile a
kernel with the ewrk3 configuration turned off and reboot.
5) insmod ewrk3.o
6) run the net startup bits for your new eth?? interface manually
(usually /etc/rc.inet[12] at boot time).
7) enjoy!
Note that autoprobing is not allowed in loadable modules - the system is
already up and running and you're messing with interrupts.
To unload a module, turn off the associated interface
'ifconfig eth?? down' then 'rmmod ewrk3'.
Promiscuous mode has been turned off in this driver, but all the
multicast address bits have been turned on. This improved the send
performance on a busy network by about 13%.
Ioctl's have now been provided (primarily because I wanted to grab some
packet size statistics). They are patterned after 'plipconfig.c' from a
suggestion by Alan Cox. Using these ioctls, you can enable promiscuous
mode, add/delete multicast addresses, change the hardware address, get
packet size distribution statistics and muck around with the control and
status register. I'll add others if and when the need arises.
TO DO:
------
Revision History
----------------
Version Date Description
0.1 26-aug-94 Initial writing. ALPHA code release.
0.11 31-aug-94 Fixed: 2k mode memory base calc.,
LeMAC version calc.,
IRQ vector assignments during autoprobe.
0.12 31-aug-94 Tested working on LeMAC2 (DE20[345]-AC) card.
Fixed up MCA hash table algorithm.
0.20 4-sep-94 Added IOCTL functionality.
0.21 14-sep-94 Added I/O mode.
0.21axp 15-sep-94 Special version for ALPHA AXP Linux V1.0
0.22 16-sep-94 Added more IOCTLs & tidied up.
0.23 21-sep-94 Added transmit cut through
0.24 31-oct-94 Added uid checks in some ioctls
0.30 1-nov-94 BETA code release
=========================================================================
*/
static
char
*
version
=
"ewrk3.c:v0.30 11/1/94 davies@wanton.lkg.dec.com
\n
"
;
#include <stdarg.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/ptrace.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/segment.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/time.h>
#include <linux/types.h>
#include <linux/unistd.h>
#ifdef MODULE
#include <linux/module.h>
#include "/linux/tools/version.h"
#endif
/* MODULE */
#include "ewrk3.h"
#ifdef EWRK3_DEBUG
static
int
ewrk3_debug
=
EWRK3_DEBUG
;
#else
static
int
ewrk3_debug
=
1
;
#endif
#ifndef PROBE_LENGTH
#define PROBE_LENGTH 32
#endif
#ifndef PROBE_SEQUENCE
#define PROBE_SEQUENCE "FF0055AAFF0055AA"
#endif
#ifndef EWRK3_SIGNATURE
#define EWRK3_SIGNATURE {"DE203","DE204","DE205",""}
#define EWRK3_NAME_LENGTH 8
#endif
#ifndef EWRK3_RAM_BASE_ADDRESSES
#define EWRK3_RAM_BASE_ADDRESSES {0xc0000,0xd0000,0x00000}
#endif
/*
** Sets up the search areas for the autoprobe. You can disable an area
** by writing a zero into the corresponding bit position in EWRK3_IO_SEARCH.
** The LSb -> I/O 0x100. Each bit increments the I/O location searched by 0x20.
** Bit 24 -> I/O 0x400.
**
** By default, probes at locations:
** 0x1e0 (may conflict with hard disk)
** 0x320 (may conflict with hard disk)
** 0x3e0 (may conflict with floppy disk)
**
** are disabled.
*/
#define EWRK3_IO_BASE 0x100
/* Start address for probe search */
#define EWRK3_IOP_INC 0x20
/* I/O address increment */
#define EWRK3_IO_SEARCH 0x007dff7f
/* probe search mask */
static
long
mem_chkd
=
EWRK3_IO_SEARCH
;
/* holds which I/O addrs should be */
/* checked, for multi-EWRK3 case */
#ifndef MAX_NUM_EWRK3S
#define MAX_NUM_EWRK3S 21
#endif
#ifndef EWRK3_EISA_IO_PORTS
#define EWRK3_EISA_IO_PORTS 0x0c00
/* I/O port base address, slot 0 */
#endif
#ifndef MAX_EISA_SLOTS
#define MAX_EISA_SLOTS 8
#define EISA_SLOT_INC 0x1000
#endif
#ifndef CRC_POLYNOMIAL
#define CRC_POLYNOMIAL 0x04c11db7
/* Ethernet CRC polynomial */
#endif
/* CRC_POLYNOMIAL */
/*
** EtherWORKS 3 shared memory window sizes
*/
#define IO_ONLY 0x00
#define SHMEM_2K 0x800
#define SHMEM_32K 0x8000
#define SHMEM_64K 0x10000
/*
** EtherWORKS 3 IRQ ENABLE/DISABLE
*/
static
unsigned
char
irq_mask
=
TNEM
|
TXDM
|
RNEM
|
RXDM
;
#define ENABLE_IRQs \
icr |= irq_mask;\
outb(icr, EWRK3_ICR)
/* Enable the IRQs */
#define DISABLE_IRQs \
icr = inb(EWRK3_ICR);\
icr &= ~irq_mask;\
outb(icr, EWRK3_ICR)
/* Disable the IRQs */
/*
** EtherWORKS 3 START/STOP
*/
#define START_EWRK3 \
csr = inb(EWRK3_CSR);\
csr &= ~(TXD|RXD);\
outb(csr, EWRK3_CSR)
/* Enable the TX and/or RX */
#define STOP_EWRK3 \
csr = (TXD|RXD);\
outb(csr, EWRK3_CSR)
/* Disable the TX and/or RX */
/*
** The EtherWORKS 3 private structure
*/
#define EWRK3_PKT_STAT_SZ 16
#define EWRK3_PKT_BIN_SZ 128
/* Should be >=100 unless you
increase EWRK3_PKT_STAT_SZ */
struct
ewrk3_private
{
long
shmem_base
;
/* Shared memory start address */
long
shmem_length
;
/* Shared memory window length */
struct
enet_statistics
stats
;
/* Public stats */
struct
{
unsigned
long
bins
[
EWRK3_PKT_STAT_SZ
];
/* Private stats counters */
unsigned
long
unicast
;
unsigned
long
multicast
;
unsigned
long
broadcast
;
unsigned
long
excessive_collisions
;
unsigned
long
tx_underruns
;
unsigned
long
excessive_underruns
;
}
pktStats
;
short
mPage
;
/* Maximum 2kB Page number */
unsigned
char
lemac
;
/* Chip rev. level */
unsigned
char
hard_strapped
;
/* Don't allow a full open */
unsigned
char
lock
;
/* Lock the page register */
unsigned
char
txc
;
/* Transmit cut through */
};
/*
** Force the EtherWORKS 3 card to be in 2kB MODE
*/
#define FORCE_2K_MODE \
shmem_length = SHMEM_2K;\
outb(((mem_start - 0x80000) >> 11), EWRK3_MBR)
/*
** Public Functions
*/
static
int
ewrk3_open
(
struct
device
*
dev
);
static
int
ewrk3_queue_pkt
(
struct
sk_buff
*
skb
,
struct
device
*
dev
);
static
void
ewrk3_interrupt
(
int
reg_ptr
);
static
int
ewrk3_close
(
struct
device
*
dev
);
static
struct
enet_statistics
*
ewrk3_get_stats
(
struct
device
*
dev
);
static
void
set_multicast_list
(
struct
device
*
dev
,
int
num_addrs
,
void
*
addrs
);
static
int
ewrk3_ioctl
(
struct
device
*
dev
,
struct
ifreq
*
rq
);
/*
** Private functions
*/
static
int
ewrk3_hw_init
(
struct
device
*
dev
,
short
iobase
);
static
void
ewrk3_init
(
struct
device
*
dev
);
static
int
ewrk3_rx
(
struct
device
*
dev
);
static
int
ewrk3_tx
(
struct
device
*
dev
);
static
void
EthwrkSignature
(
char
*
name
,
char
*
eeprom_image
);
static
int
DevicePresent
(
short
iobase
);
static
void
SetMulticastFilter
(
struct
device
*
dev
,
int
num_addrs
,
char
*
addrs
,
char
*
multicast_table
);
static
int
Read_EEPROM
(
short
iobase
,
unsigned
char
eaddr
);
static
int
Write_EEPROM
(
short
data
,
short
iobase
,
unsigned
char
eaddr
);
static
unsigned
char
aprom_crc
(
struct
device
*
dev
,
unsigned
char
*
eeprom_image
,
char
chipType
);
#ifndef MODULE
static
struct
device
*
isa_probe
(
struct
device
*
dev
);
static
struct
device
*
eisa_probe
(
struct
device
*
dev
);
static
struct
device
*
alloc_device
(
struct
device
*
dev
,
int
iobase
);
static
int
num_ewrk3s
=
0
,
num_eth
=
0
,
autoprobed
=
0
;
static
unsigned
char
irq
[]
=
{
5
,
0
,
10
,
3
,
11
,
9
,
15
,
12
};
#else
int
init_module
(
void
);
void
cleanup_module
(
void
);
#endif
/* MODULE */
/*
** Miscellaneous defines...
*/
#define INIT_EWRK3 {\
int i;\
outb(EEPROM_INIT, EWRK3_IOPR);\
for (i=0;i<5000;i++) inb(EWRK3_CSR);\
}
int
ewrk3_probe
(
struct
device
*
dev
)
{
int
base_addr
=
dev
->
base_addr
;
int
status
=
-
ENODEV
;
#ifndef MODULE
struct
device
*
eth0
;
#endif
if
(
base_addr
>
0x0ff
)
{
/* Check a single specified location. */
if
(((
mem_chkd
>>
((
base_addr
-
EWRK3_IO_BASE
)
/
EWRK3_IOP_INC
))
&
0x01
)
==
0
)
{
if
(
DevicePresent
(
base_addr
)
==
0
)
{
/* Is EWRK3 really here? */
status
=
ewrk3_hw_init
(
dev
,
base_addr
);
}
else
{
printk
(
"ewrk3_probe(): No device found
\n
"
);
}
}
else
{
status
=
ewrk3_hw_init
(
dev
,
base_addr
);
/* Yes there is h/w */
}
}
else
if
(
base_addr
>
0
)
{
/* Don't probe at all. */
status
=
-
ENXIO
;
#ifdef MODULE
}
else
{
printk
(
"Autoprobing is not supported when loading a module based driver.
\n
"
);
status
=
-
EIO
;
#else
}
else
if
(
!
autoprobed
)
{
/* First probe for the EWRK3 test */
/* pattern in ROM */
eth0
=
isa_probe
(
dev
);
eth0
=
eisa_probe
(
eth0
);
if
(
dev
->
priv
)
status
=
0
;
autoprobed
=
1
;
}
else
{
status
=
-
ENXIO
;
#endif
/* MODULE */
}
if
(
status
)
dev
->
base_addr
=
base_addr
;
return
status
;
}
static
int
ewrk3_hw_init
(
struct
device
*
dev
,
short
iobase
)
{
struct
ewrk3_private
*
lp
;
int
i
,
status
=
0
;
unsigned
long
mem_start
,
shmem_length
;
char
name
[
EWRK3_NAME_LENGTH
+
1
];
unsigned
char
cr
,
cmr
,
icr
,
nicsr
,
lemac
,
hard_strapped
=
0
;
unsigned
char
eeprom_image
[
EEPROM_MAX
],
chksum
,
eisa_cr
=
0
;
/*
** Stop the EWRK3. Enable the DBR ROM. Disable interrupts and remote boot.
** This also disables the EISA_ENABLE bit in the EISA Control Register.
*/
if
(
iobase
>
0x400
)
eisa_cr
=
inb
(
EISA_CR
);
INIT_EWRK3
;
nicsr
=
inb
(
EWRK3_CSR
);
/*
** Disable & mask all board interrupts
*/
DISABLE_IRQs
;
if
(
nicsr
==
TXD
|
RXD
)
{
/*
** Check that the EEPROM is alive and well and not living on Pluto...
*/
for
(
chksum
=
0
,
i
=
0
;
i
<
EEPROM_MAX
;
i
+=
2
)
{
union
{
short
val
;
char
c
[
2
];
}
tmp
;
tmp
.
val
=
(
short
)
Read_EEPROM
(
iobase
,
(
i
>>
1
));
eeprom_image
[
i
]
=
tmp
.
c
[
0
];
eeprom_image
[
i
+
1
]
=
tmp
.
c
[
1
];
chksum
+=
eeprom_image
[
i
]
+
eeprom_image
[
i
+
1
];
}
if
(
chksum
!=
0
)
{
/* Bad EEPROM Data! */
printk
(
"%s: Device has a bad on-board EEPROM.
\n
"
,
dev
->
name
);
status
=
-
ENXIO
;
}
else
{
/*
** Now find out what kind of EWRK3 we have.
*/
EthwrkSignature
(
name
,
eeprom_image
);
if
(
*
name
!=
'\0'
)
{
/* found a EWRK3 device */
dev
->
base_addr
=
iobase
;
if
(
iobase
>
0x400
)
{
outb
(
eisa_cr
,
EISA_CR
);
/* Rewrite the EISA CR */
}
lemac
=
eeprom_image
[
EEPROM_CHIPVER
];
cmr
=
inb
(
EWRK3_CMR
);
if
(((
lemac
==
LeMAC
)
&&
((
cmr
&
NO_EEPROM
)
!=
NO_EEPROM
))
||
((
lemac
==
LeMAC2
)
&&
!
(
cmr
&
HS
)))
{
printk
(
"%s: %s at %#3x"
,
dev
->
name
,
name
,
iobase
);
hard_strapped
=
1
;
}
else
if
((
iobase
&
0x0fff
)
==
EWRK3_EISA_IO_PORTS
)
{
/* EISA slot address */
printk
(
"%s: %s at %#3x (EISA slot %d)"
,
dev
->
name
,
name
,
iobase
,
((
iobase
>>
12
)
&
0x0f
));
}
else
{
/* ISA port address */
printk
(
"%s: %s at %#3x"
,
dev
->
name
,
name
,
iobase
);
}
if
(
!
status
)
{
printk
(
", h/w address "
);
if
(
lemac
==
LeMAC2
)
{
for
(
i
=
0
;
i
<
ETH_ALEN
-
1
;
i
++
)
{
/* get the ethernet address */
printk
(
"%2.2x:"
,
dev
->
dev_addr
[
i
]
=
eeprom_image
[
EEPROM_PADDR0
+
i
]);
outb
(
eeprom_image
[
EEPROM_PADDR0
+
i
],
EWRK3_PAR0
+
i
);
}
printk
(
"%2.2x,
\n
"
,
dev
->
dev_addr
[
i
]
=
eeprom_image
[
EEPROM_PADDR0
+
i
]);
outb
(
eeprom_image
[
EEPROM_PADDR0
+
i
],
EWRK3_PAR0
+
i
);
}
else
{
DevicePresent
(
iobase
);
/* needed after the EWRK3_INIT */
for
(
i
=
0
;
i
<
ETH_ALEN
-
1
;
i
++
)
{
/* get the ethernet addr. */
printk
(
"%2.2x:"
,
dev
->
dev_addr
[
i
]
=
inb
(
EWRK3_APROM
));
outb
(
dev
->
dev_addr
[
i
],
EWRK3_PAR0
+
i
);
}
printk
(
"%2.2x,
\n
"
,
dev
->
dev_addr
[
i
]
=
inb
(
EWRK3_APROM
));
outb
(
dev
->
dev_addr
[
i
],
EWRK3_PAR0
+
i
);
}
if
(
aprom_crc
(
dev
,
eeprom_image
,
lemac
))
{
printk
(
" which has an EEPROM CRC error.
\n
"
);
status
=
-
ENXIO
;
}
else
{
if
(
lemac
==
LeMAC2
)
{
/* Special LeMAC2 CMR things */
cmr
&=
~
(
RA
|
WB
|
LINK
|
POLARITY
|
_0WS
);
if
(
eeprom_image
[
EEPROM_MISC0
]
&
READ_AHEAD
)
cmr
|=
RA
;
if
(
eeprom_image
[
EEPROM_MISC0
]
&
WRITE_BEHIND
)
cmr
|=
WB
;
if
(
eeprom_image
[
EEPROM_NETMAN0
]
&
NETMAN_POL
)
cmr
|=
POLARITY
;
if
(
eeprom_image
[
EEPROM_NETMAN0
]
&
NETMAN_LINK
)
cmr
|=
LINK
;
if
(
eeprom_image
[
EEPROM_MISC0
]
&
_0WS_ENA
)
cmr
|=
_0WS
;
}
if
(
eeprom_image
[
EEPROM_SETUP
]
&
SETUP_DRAM
)
cmr
|=
DRAM
;
outb
(
cmr
,
EWRK3_CMR
);
cr
=
inb
(
EWRK3_CR
);
/* Set up the Control Register */
cr
|=
eeprom_image
[
EEPROM_SETUP
]
&
SETUP_APD
;
if
(
cr
&
SETUP_APD
)
cr
|=
eeprom_image
[
EEPROM_SETUP
]
&
SETUP_PS
;
cr
|=
eeprom_image
[
EEPROM_MISC0
]
&
FAST_BUS
;
cr
|=
eeprom_image
[
EEPROM_MISC0
]
&
ENA_16
;
outb
(
cr
,
EWRK3_CR
);
/*
** Determine the base address and window length for the EWRK3
** RAM from the memory base register.
*/
mem_start
=
inb
(
EWRK3_MBR
);
shmem_length
=
0
;
if
(
mem_start
!=
0
)
{
if
((
mem_start
>=
0x0a
)
&&
(
mem_start
<=
0x0f
))
{
mem_start
*=
SHMEM_64K
;
shmem_length
=
SHMEM_64K
;
}
else
if
((
mem_start
>=
0x14
)
&&
(
mem_start
<=
0x1f
))
{
mem_start
*=
SHMEM_32K
;
shmem_length
=
SHMEM_32K
;
}
else
if
((
mem_start
>=
0x40
)
&&
(
mem_start
<=
0xff
))
{
mem_start
=
mem_start
*
SHMEM_2K
+
0x80000
;
shmem_length
=
SHMEM_2K
;
}
else
{
status
=
-
ENXIO
;
}
}
/*
** See the top of this source code for comments about
** uncommenting this line.
*/
/* FORCE_2K_MODE;*/
if
(
!
status
)
{
if
(
hard_strapped
)
{
printk
(
" is hard strapped.
\n
"
);
}
else
if
(
mem_start
)
{
printk
(
" has a %dk RAM window"
,
(
int
)(
shmem_length
>>
10
));
printk
(
" at 0x%.5lx"
,
mem_start
);
}
else
{
printk
(
" is in I/O only mode"
);
}
/* private area & initialise */
dev
->
priv
=
(
void
*
)
kmalloc
(
sizeof
(
struct
ewrk3_private
),
GFP_KERNEL
);
lp
=
(
struct
ewrk3_private
*
)
dev
->
priv
;
memset
(
dev
->
priv
,
0
,
sizeof
(
struct
ewrk3_private
));
lp
->
shmem_base
=
mem_start
;
lp
->
shmem_length
=
shmem_length
;
lp
->
lemac
=
lemac
;
lp
->
hard_strapped
=
hard_strapped
;
lp
->
mPage
=
64
;
if
(
cmr
&
DRAM
)
lp
->
mPage
<<=
1
;
/* 2 DRAMS on module */
if
(
!
hard_strapped
)
{
/*
** Enable EWRK3 board interrupts for autoprobing
*/
icr
|=
IE
;
/* Enable interrupts */
outb
(
icr
,
EWRK3_ICR
);
/* The DMA channel may be passed in on this parameter. */
dev
->
dma
=
0
;
/* To auto-IRQ we enable the initialization-done and DMA err,
interrupts. For now we will always get a DMA error. */
if
(
dev
->
irq
<
2
)
{
#ifndef MODULE
unsigned
char
irqnum
;
autoirq_setup
(
0
);
/*
** Trigger a TNE interrupt.
*/
icr
|=
TNEM
;
outb
(
1
,
EWRK3_TDQ
);
/* Write to the TX done queue */
outb
(
icr
,
EWRK3_ICR
);
/* Unmask the TXD interrupt */
irqnum
=
irq
[((
icr
&
IRQ_SEL
)
>>
4
)];
dev
->
irq
=
autoirq_report
(
1
);
if
((
dev
->
irq
)
&&
(
irqnum
==
dev
->
irq
))
{
printk
(
" and uses IRQ%d.
\n
"
,
dev
->
irq
);
}
else
{
if
(
!
dev
->
irq
)
{
printk
(
" and failed to detect IRQ line.
\n
"
);
}
else
if
((
irqnum
==
1
)
&&
(
lemac
==
LeMAC2
))
{
printk
(
" and an illegal IRQ line detected.
\n
"
);
}
else
{
printk
(
", but incorrect IRQ line detected.
\n
"
);
}
status
=
-
ENXIO
;
}
DISABLE_IRQs
;
/* Mask all interrupts */
#endif
/* MODULE */
}
else
{
printk
(
" and requires IRQ%d.
\n
"
,
dev
->
irq
);
}
}
}
else
{
status
=
-
ENXIO
;
}
}
}
}
else
{
status
=
-
ENXIO
;
}
}
if
(
!
status
)
{
if
(
ewrk3_debug
>
0
)
{
printk
(
version
);
}
/* The EWRK3-specific entries in the device structure. */
dev
->
open
=
&
ewrk3_open
;
dev
->
hard_start_xmit
=
&
ewrk3_queue_pkt
;
dev
->
stop
=
&
ewrk3_close
;
dev
->
get_stats
=
&
ewrk3_get_stats
;
#ifdef HAVE_MULTICAST
dev
->
set_multicast_list
=
&
set_multicast_list
;
#endif
dev
->
do_ioctl
=
&
ewrk3_ioctl
;
dev
->
mem_start
=
0
;
/* Fill in the generic field of the device structure. */
ether_setup
(
dev
);
}
}
else
{
status
=
-
ENXIO
;
}
return
status
;
}
static
int
ewrk3_open
(
struct
device
*
dev
)
{
struct
ewrk3_private
*
lp
=
(
struct
ewrk3_private
*
)
dev
->
priv
;
int
i
,
iobase
=
dev
->
base_addr
;
int
status
=
0
;
unsigned
char
icr
,
csr
;
/*
** Stop the TX and RX...
*/
STOP_EWRK3
;
if
(
!
lp
->
hard_strapped
)
{
if
(
request_irq
(
dev
->
irq
,
&
ewrk3_interrupt
,
0
,
"ewrk3"
))
{
printk
(
"ewrk3_open(): Requested IRQ%d is busy
\n
"
,
dev
->
irq
);
status
=
-
EAGAIN
;
}
else
{
irq2dev_map
[
dev
->
irq
]
=
dev
;
/*
** Re-initialize the EWRK3...
*/
ewrk3_init
(
dev
);
if
(
ewrk3_debug
>
1
){
printk
(
"%s: ewrk3 open with irq %d
\n
"
,
dev
->
name
,
dev
->
irq
);
printk
(
"
\t
physical address: "
);
for
(
i
=
0
;
i
<
6
;
i
++
){
printk
(
"%2.2x:"
,(
short
)
dev
->
dev_addr
[
i
]);
}
printk
(
"
\n
"
);
printk
(
"
\t
checked memory: 0x%08lx
\n
"
,
mem_chkd
);
if
(
lp
->
shmem_length
==
0
)
{
printk
(
"
\t
no shared memory, I/O only mode
\n
"
);
}
else
{
printk
(
"
\t
start of shared memory: 0x%08lx
\n
"
,
lp
->
shmem_base
);
printk
(
"
\t
window length: 0x%04lx
\n
"
,
lp
->
shmem_length
);
}
printk
(
"
\t
# of DRAMS: %d
\n
"
,((
inb
(
EWRK3_CMR
)
&
0x02
)
?
2
:
1
));
printk
(
"
\t
csr: 0x%02x
\n
"
,
inb
(
EWRK3_CSR
));
printk
(
"
\t
cr: 0x%02x
\n
"
,
inb
(
EWRK3_CR
));
printk
(
"
\t
icr: 0x%02x
\n
"
,
inb
(
EWRK3_ICR
));
printk
(
"
\t
cmr: 0x%02x
\n
"
,
inb
(
EWRK3_CMR
));
printk
(
"
\t
fmqc: 0x%02x
\n
"
,
inb
(
EWRK3_FMQC
));
}
dev
->
tbusy
=
0
;
dev
->
start
=
1
;
dev
->
interrupt
=
UNMASK_INTERRUPTS
;
/*
** Unmask EWRK3 board interrupts
*/
icr
=
inb
(
EWRK3_ICR
);
ENABLE_IRQs
;
}
}
else
{
dev
->
start
=
0
;
dev
->
tbusy
=
1
;
printk
(
"%s: ewrk3 available for hard strapped set up only.
\n
"
,
dev
->
name
);
printk
(
" Run the 'ewrk3setup' utility or remove the hard straps.
\n
"
);
}
#ifdef MODULE
MOD_INC_USE_COUNT
;
#endif
return
status
;
}
/*
** Initialize the EtherWORKS 3 operating conditions
*/
static
void
ewrk3_init
(
struct
device
*
dev
)
{
struct
ewrk3_private
*
lp
=
(
struct
ewrk3_private
*
)
dev
->
priv
;
char
csr
,
page
;
short
iobase
=
dev
->
base_addr
;
/*
** Enable all multicasts
*/
set_multicast_list
(
dev
,
HASH_TABLE_LEN
,
NULL
);
/*
** Clean out any remaining entries in all the queues here
*/
while
(
inb
(
EWRK3_TQ
));
while
(
inb
(
EWRK3_TDQ
));
while
(
inb
(
EWRK3_RQ
));
while
(
inb
(
EWRK3_FMQ
));
/*
** Write a clean free memory queue
*/
for
(
page
=
1
;
page
<
lp
->
mPage
;
page
++
)
{
/* Write the free page numbers */
outb
(
page
,
EWRK3_FMQ
);
/* to the Free Memory Queue */
}
lp
->
lock
=
0
;
/* Ensure there are no locks */
START_EWRK3
;
/* Enable the TX and/or RX */
}
/*
** Writes a socket buffer to the free page queue
*/
static
int
ewrk3_queue_pkt
(
struct
sk_buff
*
skb
,
struct
device
*
dev
)
{
struct
ewrk3_private
*
lp
=
(
struct
ewrk3_private
*
)
dev
->
priv
;
int
iobase
=
dev
->
base_addr
;
int
status
=
0
;
unsigned
char
icr
,
csr
;
/* Transmitter timeout, serious problems. */
if
(
dev
->
tbusy
||
lp
->
lock
)
{
int
tickssofar
=
jiffies
-
dev
->
trans_start
;
if
(
tickssofar
<
10
)
{
status
=
-
1
;
}
else
if
(
!
lp
->
hard_strapped
)
{
printk
(
"%s: transmit timed/locked out, status %04x, resetting.
\n
"
,
dev
->
name
,
inb
(
EWRK3_CSR
));
/*
** Mask all board interrupts
*/
DISABLE_IRQs
;
/*
** Stop the TX and RX...
*/
STOP_EWRK3
;
ewrk3_init
(
dev
);
/*
** Unmask EWRK3 board interrupts
*/
ENABLE_IRQs
;
dev
->
tbusy
=
0
;
dev
->
trans_start
=
jiffies
;
}
}
else
if
(
skb
==
NULL
)
{
dev_tint
(
dev
);
}
else
if
(
skb
->
len
>
0
)
{
/*
** Block a timer-based transmit from overlapping. This could better be
** done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
*/
if
(
set_bit
(
0
,
(
void
*
)
&
dev
->
tbusy
)
!=
0
)
printk
(
"%s: Transmitter access conflict.
\n
"
,
dev
->
name
);
DISABLE_IRQs
;
/* So that the page # remains correct */
/*
** Get a free page from the FMQ when resources are available
*/
if
(
inb
(
EWRK3_FMQC
)
>
0
)
{
unsigned
char
*
buf
;
unsigned
char
page
;
if
((
page
=
inb
(
EWRK3_FMQ
))
<
lp
->
mPage
)
{
buf
=
NULL
;
/*
** Set up shared memory window and pointer into the window
*/
while
(
set_bit
(
0
,
(
void
*
)
&
lp
->
lock
)
!=
0
);
/* Wait for lock to free */
if
(
lp
->
shmem_length
==
IO_ONLY
)
{
outb
(
page
,
EWRK3_IOPR
);
}
else
if
(
lp
->
shmem_length
==
SHMEM_2K
)
{
buf
=
(
char
*
)
lp
->
shmem_base
;
outb
(
page
,
EWRK3_MPR
);
}
else
if
(
lp
->
shmem_length
==
SHMEM_32K
)
{
buf
=
(
char
*
)((((
short
)
page
<<
11
)
&
0x7800
)
+
lp
->
shmem_base
);
outb
((
page
>>
4
),
EWRK3_MPR
);
}
else
if
(
lp
->
shmem_length
==
SHMEM_64K
)
{
buf
=
(
char
*
)((((
short
)
page
<<
11
)
&
0xf800
)
+
lp
->
shmem_base
);
outb
((
page
>>
5
),
EWRK3_MPR
);
}
else
{
status
=
-
1
;
printk
(
"%s: Oops - your private data area is hosed!
\n
"
,
dev
->
name
);
}
if
(
!
status
)
{
/*
** Set up the buffer control structures and copy the data from
** the socket buffer to the shared memory .
*/
if
(
lp
->
shmem_length
==
IO_ONLY
)
{
int
i
;
unsigned
char
*
p
=
skb
->
data
;
outb
((
char
)(
QMODE
|
PAD
|
IFC
),
EWRK3_DATA
);
outb
((
char
)(
skb
->
len
&
0xff
),
EWRK3_DATA
);
outb
((
char
)((
skb
->
len
>>
8
)
&
0xff
),
EWRK3_DATA
);
outb
((
char
)
0x04
,
EWRK3_DATA
);
for
(
i
=
0
;
i
<
skb
->
len
;
i
++
)
{
outb
(
*
p
++
,
EWRK3_DATA
);
}
outb
(
page
,
EWRK3_TQ
);
/* Start sending pkt */
}
else
{
*
buf
++
=
(
char
)(
QMODE
|
PAD
|
IFC
);
/* control byte */
*
buf
++
=
(
char
)(
skb
->
len
&
0xff
);
/* length (16 bit xfer)*/
if
(
lp
->
txc
)
{
*
buf
++
=
(
char
)(((
skb
->
len
>>
8
)
&
0xff
)
|
XCT
);
*
buf
++
=
0x04
;
/* index byte */
*
(
buf
+
skb
->
len
)
=
0x00
;
/* Write the XCT flag */
memcpy
(
buf
,
skb
->
data
,
PRELOAD
);
/* Write PRELOAD bytes */
outb
(
page
,
EWRK3_TQ
);
/* Start sending pkt */
memcpy
(
buf
+
PRELOAD
,
skb
->
data
+
PRELOAD
,
skb
->
len
-
PRELOAD
);
*
(
buf
+
skb
->
len
)
=
0xff
;
/* Write the XCT flag */
}
else
{
*
buf
++
=
(
char
)((
skb
->
len
>>
8
)
&
0xff
);
*
buf
++
=
0x04
;
/* index byte */
memcpy
(
buf
,
skb
->
data
,
skb
->
len
);
/* Write data bytes */
outb
(
page
,
EWRK3_TQ
);
/* Start sending pkt */
}
}
dev
->
trans_start
=
jiffies
;
dev_kfree_skb
(
skb
,
FREE_WRITE
);
}
else
{
/* return unused page to the free memory queue */
outb
(
page
,
EWRK3_FMQ
);
}
lp
->
lock
=
0
;
/* unlock the page register */
}
else
{
printk
(
"ewrk3_queue_pkt(): Invalid free memory page (%d).
\n
"
,
(
unsigned
char
)
page
);
}
}
else
{
printk
(
"ewrk3_queue_pkt(): No free resources...
\n
"
);
printk
(
"ewrk3_queue_pkt(): CSR: %02x ICR: %02x FMQC: %02x
\n
"
,
inb
(
EWRK3_CSR
),
inb
(
EWRK3_ICR
),
inb
(
EWRK3_FMQC
));
}
/* Check for free resources: clear 'tbusy' if there are some */
if
(
inb
(
EWRK3_FMQC
)
>
0
)
{
dev
->
tbusy
=
0
;
}
ENABLE_IRQs
;
}
return
status
;
}
/*
** The EWRK3 interrupt handler.
*/
static
void
ewrk3_interrupt
(
int
reg_ptr
)
{
int
irq
=
-
(((
struct
pt_regs
*
)
reg_ptr
)
->
orig_eax
+
2
);
struct
device
*
dev
=
(
struct
device
*
)(
irq2dev_map
[
irq
]);
struct
ewrk3_private
*
lp
;
int
iobase
;
unsigned
char
icr
,
cr
,
csr
;
if
(
dev
==
NULL
)
{
printk
(
"ewrk3_interrupt(): irq %d for unknown device.
\n
"
,
irq
);
}
else
{
lp
=
(
struct
ewrk3_private
*
)
dev
->
priv
;
iobase
=
dev
->
base_addr
;
if
(
dev
->
interrupt
)
printk
(
"%s: Re-entering the interrupt handler.
\n
"
,
dev
->
name
);
dev
->
interrupt
=
MASK_INTERRUPTS
;
/* get the interrupt information */
csr
=
inb
(
EWRK3_CSR
);
/*
** Mask the EWRK3 board interrupts and turn on the LED
*/
DISABLE_IRQs
;
cr
=
inb
(
EWRK3_CR
);
cr
|=
LED
;
outb
(
cr
,
EWRK3_CR
);
if
(
csr
&
RNE
)
/* Rx interrupt (packet[s] arrived) */
ewrk3_rx
(
dev
);
if
(
csr
&
TNE
)
/* Tx interrupt (packet sent) */
ewrk3_tx
(
dev
);
/*
** Now deal with the TX/RX disable flags. These are set when there
** are no more resources. If resources free up then enable these
** interrupts, otherwise mask them - failure to do this will result
** in the system hanging in an interrupt loop.
*/
if
(
inb
(
EWRK3_FMQC
))
{
/* any resources available? */
irq_mask
|=
TXDM
|
RXDM
;
/* enable the interrupt source */
csr
&=
~
(
TXD
|
RXD
);
/* ensure restart of a stalled TX or RX */
outb
(
csr
,
EWRK3_CSR
);
dev
->
tbusy
=
0
;
/* clear TX busy flag */
mark_bh
(
NET_BH
);
}
else
{
irq_mask
&=
~
(
TXDM
|
RXDM
);
/* disable the interrupt source */
}
/* Unmask the EWRK3 board interrupts and turn off the LED */
cr
&=
~
LED
;
outb
(
cr
,
EWRK3_CR
);
dev
->
interrupt
=
UNMASK_INTERRUPTS
;
ENABLE_IRQs
;
}
return
;
}
static
int
ewrk3_rx
(
struct
device
*
dev
)
{
struct
ewrk3_private
*
lp
=
(
struct
ewrk3_private
*
)
dev
->
priv
;
int
i
,
iobase
=
dev
->
base_addr
;
unsigned
char
page
,
tmpPage
=
0
,
tmpLock
=
0
,
*
buf
;
int
status
=
0
;
while
(
inb
(
EWRK3_RQC
)
&&
!
status
)
{
/* Whilst there's incoming data */
if
((
page
=
inb
(
EWRK3_RQ
))
<
lp
->
mPage
)
{
/* Get next entry's buffer page */
buf
=
NULL
;
/*
** Preempt any process using the current page register. Check for
** an existing lock to reduce time taken in I/O transactions.
*/
if
((
tmpLock
=
set_bit
(
0
,
(
void
*
)
&
lp
->
lock
))
==
1
)
{
/* Assert lock */
if
(
lp
->
shmem_length
==
IO_ONLY
)
{
/* Get existing page */
tmpPage
=
inb
(
EWRK3_IOPR
);
}
else
{
tmpPage
=
inb
(
EWRK3_MPR
);
}
}
/*
** Set up shared memory window and pointer into the window
*/
if
(
lp
->
shmem_length
==
IO_ONLY
)
{
outb
(
page
,
EWRK3_IOPR
);
}
else
if
(
lp
->
shmem_length
==
SHMEM_2K
)
{
buf
=
(
char
*
)
lp
->
shmem_base
;
outb
(
page
,
EWRK3_MPR
);
}
else
if
(
lp
->
shmem_length
==
SHMEM_32K
)
{
buf
=
(
char
*
)((((
short
)
page
<<
11
)
&
0x7800
)
+
lp
->
shmem_base
);
outb
((
page
>>
4
),
EWRK3_MPR
);
}
else
if
(
lp
->
shmem_length
==
SHMEM_64K
)
{
buf
=
(
char
*
)((((
short
)
page
<<
11
)
&
0xf800
)
+
lp
->
shmem_base
);
outb
((
page
>>
5
),
EWRK3_MPR
);
}
else
{
status
=
-
1
;
printk
(
"%s: Oops - your private data area is hosed!
\n
"
,
dev
->
name
);
}
if
(
!
status
)
{
char
rx_status
;
int
pkt_len
;
if
(
lp
->
shmem_length
==
IO_ONLY
)
{
rx_status
=
inb
(
EWRK3_DATA
);
pkt_len
=
inb
(
EWRK3_DATA
);
pkt_len
|=
((
unsigned
short
)
inb
(
EWRK3_DATA
)
<<
8
);
}
else
{
rx_status
=
(
char
)(
*
buf
++
);
pkt_len
=
(
short
)(
*
buf
+
((
*
(
buf
+
1
))
<<
8
));
buf
+=
3
;
}
if
(
!
(
rx_status
&
ROK
))
{
/* There was an error. */
lp
->
stats
.
rx_errors
++
;
/* Update the error stats. */
if
(
rx_status
&
DBE
)
lp
->
stats
.
rx_frame_errors
++
;
if
(
rx_status
&
CRC
)
lp
->
stats
.
rx_crc_errors
++
;
if
(
rx_status
&
PLL
)
lp
->
stats
.
rx_fifo_errors
++
;
}
else
{
struct
sk_buff
*
skb
;
if
((
skb
=
alloc_skb
(
pkt_len
,
GFP_ATOMIC
))
!=
NULL
)
{
skb
->
len
=
pkt_len
;
skb
->
dev
=
dev
;
if
(
lp
->
shmem_length
==
IO_ONLY
)
{
unsigned
char
*
p
=
skb
->
data
;
*
p
=
inb
(
EWRK3_DATA
);
/* dummy read */
for
(
i
=
0
;
i
<
skb
->
len
;
i
++
)
{
*
p
++
=
inb
(
EWRK3_DATA
);
}
}
else
{
memcpy
(
skb
->
data
,
buf
,
pkt_len
);
}
/*
** Notify the upper protocol layers that there is another
** packet to handle
*/
netif_rx
(
skb
);
/*
** Update stats
*/
lp
->
stats
.
rx_packets
++
;
for
(
i
=
1
;
i
<
EWRK3_PKT_STAT_SZ
-
1
;
i
++
)
{
if
(
pkt_len
<
i
*
EWRK3_PKT_BIN_SZ
)
{
lp
->
pktStats
.
bins
[
i
]
++
;
i
=
EWRK3_PKT_STAT_SZ
;
}
}
buf
=
skb
->
data
;
/* Look at the dest addr */
if
(
buf
[
0
]
&
0x01
)
{
/* Multicast/Broadcast */
if
((
*
(
long
*
)
&
buf
[
0
]
==
-
1
)
&&
(
*
(
short
*
)
&
buf
[
4
]
==
-
1
))
{
lp
->
pktStats
.
broadcast
++
;
}
else
{
lp
->
pktStats
.
multicast
++
;
}
}
else
if
((
*
(
long
*
)
&
buf
[
0
]
==
*
(
long
*
)
&
dev
->
dev_addr
[
0
])
&&
(
*
(
short
*
)
&
buf
[
4
]
==
*
(
short
*
)
&
dev
->
dev_addr
[
4
]))
{
lp
->
pktStats
.
unicast
++
;
}
lp
->
pktStats
.
bins
[
0
]
++
;
/* Duplicates stats.rx_packets */
if
(
lp
->
pktStats
.
bins
[
0
]
==
0
)
{
/* Reset counters */
memset
(
&
lp
->
pktStats
,
0
,
sizeof
(
lp
->
pktStats
));
}
}
else
{
printk
(
"%s: Insufficient memory; nuking packet.
\n
"
,
dev
->
name
);
lp
->
stats
.
rx_dropped
++
;
/* Really, deferred. */
break
;
}
}
}
/*
** Return the received buffer to the free memory queue
*/
outb
(
page
,
EWRK3_FMQ
);
if
(
tmpLock
)
{
/* If a lock was preempted */
if
(
lp
->
shmem_length
==
IO_ONLY
)
{
/* Replace old page */
outb
(
tmpPage
,
EWRK3_IOPR
);
}
else
{
outb
(
tmpPage
,
EWRK3_MPR
);
}
}
lp
->
lock
=
0
;
/* Unlock the page register */
}
else
{
printk
(
"ewrk3_rx(): Illegal page number, page %d
\n
"
,
page
);
printk
(
"ewrk3_rx(): CSR: %02x ICR: %02x FMQC: %02x
\n
"
,
inb
(
EWRK3_CSR
),
inb
(
EWRK3_ICR
),
inb
(
EWRK3_FMQC
));
}
}
return
status
;
}
/*
** Buffer sent - check for TX buffer errors.
*/
static
int
ewrk3_tx
(
struct
device
*
dev
)
{
struct
ewrk3_private
*
lp
=
(
struct
ewrk3_private
*
)
dev
->
priv
;
int
iobase
=
dev
->
base_addr
;
unsigned
char
tx_status
;
while
((
tx_status
=
inb
(
EWRK3_TDQ
))
>
0
)
{
/* Whilst there's old buffers */
if
(
tx_status
&
VSTS
)
{
/* The status is valid */
if
(
tx_status
&
MAC_TXE
)
{
lp
->
stats
.
tx_errors
++
;
if
(
tx_status
&
MAC_NCL
)
lp
->
stats
.
tx_carrier_errors
++
;
if
(
tx_status
&
MAC_LCL
)
lp
->
stats
.
tx_window_errors
++
;
if
(
tx_status
&
MAC_CTU
)
{
if
((
tx_status
&
MAC_COLL
)
^
MAC_XUR
)
{
lp
->
pktStats
.
tx_underruns
++
;
}
else
{
lp
->
pktStats
.
excessive_underruns
++
;
}
}
else
if
(
tx_status
&
MAC_COLL
)
{
if
((
tx_status
&
MAC_COLL
)
^
MAC_XCOLL
)
{
lp
->
stats
.
collisions
++
;
}
else
{
lp
->
pktStats
.
excessive_collisions
++
;
}
}
}
else
{
lp
->
stats
.
tx_packets
++
;
}
}
}
return
0
;
}
static
int
ewrk3_close
(
struct
device
*
dev
)
{
struct
ewrk3_private
*
lp
=
(
struct
ewrk3_private
*
)
dev
->
priv
;
int
iobase
=
dev
->
base_addr
;
unsigned
char
icr
,
csr
;
dev
->
start
=
0
;
dev
->
tbusy
=
1
;
if
(
ewrk3_debug
>
1
)
{
printk
(
"%s: Shutting down ethercard, status was %2.2x.
\n
"
,
dev
->
name
,
inb
(
EWRK3_CSR
));
}
/*
** We stop the EWRK3 here... mask interrupts and stop TX & RX
*/
DISABLE_IRQs
;
STOP_EWRK3
;
/*
** Clean out the TX and RX queues here (note that one entry
** may get added to either the TXD or RX queues if the the TX or RX
** just starts processing a packet before the STOP_EWRK3 command
** is received. This will be flushed in the ewrk3_open() call).
*/
while
(
inb
(
EWRK3_TQ
));
while
(
inb
(
EWRK3_TDQ
));
while
(
inb
(
EWRK3_RQ
));
if
(
!
lp
->
hard_strapped
)
{
free_irq
(
dev
->
irq
);
irq2dev_map
[
dev
->
irq
]
=
0
;
}
#ifdef MODULE
MOD_DEC_USE_COUNT
;
#endif
return
0
;
}
static
struct
enet_statistics
*
ewrk3_get_stats
(
struct
device
*
dev
)
{
struct
ewrk3_private
*
lp
=
(
struct
ewrk3_private
*
)
dev
->
priv
;
/* Null body since there is no framing error counter */
return
&
lp
->
stats
;
}
/*
** Set or clear the multicast filter for this adaptor.
** num_addrs == -1 Promiscuous mode, receive all packets
** num_addrs == 0 Normal mode, clear multicast list
** num_addrs > 0 Multicast mode, receive normal and MC packets, and do
** best-effort filtering.
*/
static
void
set_multicast_list
(
struct
device
*
dev
,
int
num_addrs
,
void
*
addrs
)
{
struct
ewrk3_private
*
lp
=
(
struct
ewrk3_private
*
)
dev
->
priv
;
int
iobase
=
dev
->
base_addr
;
char
*
multicast_table
;
unsigned
char
csr
;
csr
=
inb
(
EWRK3_CSR
);
if
(
lp
->
shmem_length
==
IO_ONLY
)
{
multicast_table
=
(
char
*
)
PAGE0_HTE
;
}
else
{
multicast_table
=
(
char
*
)(
lp
->
shmem_base
+
PAGE0_HTE
);
}
if
(
num_addrs
>=
0
)
{
SetMulticastFilter
(
dev
,
num_addrs
,
(
char
*
)
addrs
,
multicast_table
);
csr
&=
~
PME
;
csr
|=
MCE
;
outb
(
csr
,
EWRK3_CSR
);
}
else
{
/* set promiscuous mode */
csr
|=
PME
;
csr
&=
~
MCE
;
outb
(
csr
,
EWRK3_CSR
);
}
}
/*
** Calculate the hash code and update the logical address filter
** from a list of ethernet multicast addresses.
** Derived from a 'C' program in the AMD data book:
** "Am79C90 CMOS Local Area Network Controller for Ethernet (C-LANCE)",
** Pub #17781, Rev. A, May 1993
**
*/
static
void
SetMulticastFilter
(
struct
device
*
dev
,
int
num_addrs
,
char
*
addrs
,
char
*
multicast_table
)
{
struct
ewrk3_private
*
lp
=
(
struct
ewrk3_private
*
)
dev
->
priv
;
int
iobase
=
dev
->
base_addr
;
char
j
,
ctrl
,
bit
,
octet
;
short
*
p
=
(
short
*
)
multicast_table
;
unsigned
short
hashcode
;
int
i
;
long
int
crc
,
poly
=
(
long
int
)
CRC_POLYNOMIAL
;
while
(
set_bit
(
0
,
(
void
*
)
&
lp
->
lock
)
!=
0
);
/* Wait for lock to free */
if
(
lp
->
shmem_length
==
IO_ONLY
)
{
outb
(
0
,
EWRK3_IOPR
);
outw
((
short
)((
long
)
multicast_table
),
EWRK3_PIR1
);
}
else
{
outb
(
0
,
EWRK3_MPR
);
}
if
(
num_addrs
==
HASH_TABLE_LEN
)
{
for
(
i
=
0
;
i
<
(
HASH_TABLE_LEN
>>
3
);
i
++
)
{
if
(
lp
->
shmem_length
==
IO_ONLY
)
{
outb
(
0xff
,
EWRK3_DATA
);
}
else
{
/* memset didn't work here */
*
p
++
=
0xffff
;
i
++
;
}
}
}
else
if
(
num_addrs
==
0
)
{
if
(
lp
->
shmem_length
==
IO_ONLY
)
{
for
(
i
=
0
;
i
<
(
HASH_TABLE_LEN
>>
3
);
i
++
)
{
outb
(
0x00
,
EWRK3_DATA
);
}
}
else
{
memset
(
multicast_table
,
0
,
(
HASH_TABLE_LEN
>>
3
));
}
}
else
{
for
(
i
=
0
;
i
<
num_addrs
;
i
++
)
{
/* for each address in the list */
if
(((
char
)
*
(
addrs
+
ETH_ALEN
*
i
)
&
0x01
)
==
1
)
{
/* multicast address? */
crc
=
(
long
int
)
0xffffffff
;
/* init CRC for each address */
for
(
octet
=
0
;
octet
<
ETH_ALEN
;
octet
++
)
{
/* for each address octet */
for
(
j
=
0
;
j
<
8
;
j
++
)
{
/* process each address bit */
bit
=
(((
char
)
*
(
addrs
+
ETH_ALEN
*
i
+
octet
))
>>
j
)
&
0x01
;
ctrl
=
((
crc
<
0
)
?
1
:
0
);
/* shift the control bit */
crc
<<=
1
;
/* shift the CRC */
if
(
bit
^
ctrl
)
{
/* (bit) XOR (control bit) */
crc
^=
poly
;
/* (CRC) XOR (polynomial) */
}
}
}
hashcode
=
(
crc
&
0x01
);
/* hashcode is 9 LSb of CRC ... */
for
(
j
=
0
;
j
<
8
;
j
++
)
{
/* ... in reverse order. */
hashcode
<<=
1
;
crc
>>=
1
;
hashcode
|=
(
crc
&
0x01
);
}
octet
=
hashcode
>>
3
;
/* bit[3-8] -> octet in filter */
/* bit[0-2] -> bit in octet */
if
(
lp
->
shmem_length
==
IO_ONLY
)
{
unsigned
char
tmp
;
outw
((
short
)((
long
)
multicast_table
)
+
octet
,
EWRK3_PIR1
);
tmp
=
inb
(
EWRK3_DATA
);
tmp
|=
(
1
<<
(
hashcode
&
0x07
));
outw
((
short
)((
long
)
multicast_table
)
+
octet
,
EWRK3_PIR1
);
outb
(
tmp
,
EWRK3_DATA
);
}
else
{
multicast_table
[
octet
]
|=
(
1
<<
(
hashcode
&
0x07
));
}
}
}
}
lp
->
lock
=
0
;
/* Unlock the page register */
return
;
}
#ifndef MODULE
/*
** ISA bus I/O device probe
*/
static
struct
device
*
isa_probe
(
struct
device
*
dev
)
{
int
i
,
iobase
,
status
;
unsigned
long
int
tmp
=
mem_chkd
;
for
(
status
=
-
ENODEV
,
iobase
=
EWRK3_IO_BASE
,
i
=
0
;
i
<
24
;
iobase
+=
EWRK3_IOP_INC
,
i
++
)
{
if
(
tmp
&
0x01
)
{
if
(
DevicePresent
(
iobase
)
==
0
)
{
/*
** Device found. Mark its (I/O) location for future reference. Only 24
** EtherWORKS devices can exist between 0x100 and 0x3e0.
*/
if
(
num_ewrk3s
>
0
)
{
/* only gets here in autoprobe */
dev
=
alloc_device
(
dev
,
iobase
);
}
else
{
if
((
status
=
ewrk3_hw_init
(
dev
,
iobase
))
==
0
)
{
num_ewrk3s
++
;
}
}
num_eth
++
;
}
else
{
mem_chkd
&=
~
(
0x01
<<
((
iobase
-
EWRK3_IO_BASE
)
/
EWRK3_IOP_INC
));
}
}
tmp
>>=
1
;
}
return
dev
;
}
/*
** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
** the motherboard.
*/
static
struct
device
*
eisa_probe
(
struct
device
*
dev
)
{
int
i
,
iobase
=
EWRK3_EISA_IO_PORTS
;
int
status
;
iobase
+=
EISA_SLOT_INC
;
/* get the first slot address */
for
(
status
=
-
ENODEV
,
i
=
1
;
i
<
MAX_EISA_SLOTS
;
i
++
,
iobase
+=
EISA_SLOT_INC
)
{
if
(
DevicePresent
(
iobase
)
==
0
)
{
/*
** Device found. Mark its slot location for future reference. Only 7
** EtherWORKS devices can exist in EISA space....
*/
mem_chkd
|=
(
0x01
<<
(
i
+
24
));
if
(
num_ewrk3s
>
0
)
{
/* only gets here in autoprobe */
dev
=
alloc_device
(
dev
,
iobase
);
}
else
{
if
((
status
=
ewrk3_hw_init
(
dev
,
iobase
))
==
0
)
{
num_ewrk3s
++
;
}
}
num_eth
++
;
}
}
return
dev
;
}
/*
** Allocate the device by pointing to the next available space in the
** device structure. Should one not be available, it is created.
*/
static
struct
device
*
alloc_device
(
struct
device
*
dev
,
int
iobase
)
{
/*
** Check the device structures for an end of list or unused device
*/
while
(
dev
->
next
!=
NULL
)
{
if
(
dev
->
next
->
base_addr
==
0xffe0
)
break
;
dev
=
dev
->
next
;
/* walk through eth device list */
num_eth
++
;
/* increment eth device number */
}
/*
** If no more device structures, malloc one up. If memory could
** not be allocated, print an error message.
*/
if
(
dev
->
next
==
NULL
)
{
dev
->
next
=
(
struct
device
*
)
kmalloc
(
sizeof
(
struct
device
)
+
8
,
GFP_KERNEL
);
if
(
dev
->
next
==
NULL
)
{
printk
(
"eth%d: Device not initialised, insufficient memory
\n
"
,
num_eth
);
}
}
/*
** If the memory was allocated, point to the new memory area
** and initialize it (name, I/O address, next device (NULL) and
** initialisation probe routine).
*/
if
((
dev
->
next
!=
NULL
)
&&
(
num_eth
>
0
)
&&
(
num_eth
<
9999
))
{
dev
=
dev
->
next
;
/* point to the new device */
dev
->
name
=
(
char
*
)(
dev
+
sizeof
(
struct
device
));
sprintf
(
dev
->
name
,
"eth%d"
,
num_eth
);
/* New device name */
dev
->
base_addr
=
iobase
;
/* assign the io address */
dev
->
next
=
NULL
;
/* mark the end of list */
dev
->
init
=
&
ewrk3_probe
;
/* initialisation routine */
num_ewrk3s
++
;
}
return
dev
;
}
#endif
/* MODULE */
/*
** Read the EWRK3 EEPROM using this routine
*/
static
int
Read_EEPROM
(
short
iobase
,
unsigned
char
eaddr
)
{
int
i
;
outb
((
eaddr
&
0x3f
),
EWRK3_PIR1
);
/* set up 6 bits of address info */
outb
(
EEPROM_RD
,
EWRK3_IOPR
);
/* issue read command */
for
(
i
=
0
;
i
<
5000
;
i
++
)
inb
(
EWRK3_CSR
);
/* wait 1msec */
return
inw
(
EWRK3_EPROM1
);
/* 16 bits data return */
}
/*
** Write the EWRK3 EEPROM using this routine
*/
static
int
Write_EEPROM
(
short
data
,
short
iobase
,
unsigned
char
eaddr
)
{
int
i
;
outb
(
EEPROM_WR_EN
,
EWRK3_IOPR
);
/* issue write enable command */
for
(
i
=
0
;
i
<
5000
;
i
++
)
inb
(
EWRK3_CSR
);
/* wait 1msec */
outw
(
data
,
EWRK3_EPROM1
);
/* write data to register */
outb
((
eaddr
&
0x3f
),
EWRK3_PIR1
);
/* set up 6 bits of address info */
outb
(
EEPROM_WR
,
EWRK3_IOPR
);
/* issue write command */
for
(
i
=
0
;
i
<
75000
;
i
++
)
inb
(
EWRK3_CSR
);
/* wait 15msec */
outb
(
EEPROM_WR_DIS
,
EWRK3_IOPR
);
/* issue write disable command */
for
(
i
=
0
;
i
<
5000
;
i
++
)
inb
(
EWRK3_CSR
);
/* wait 1msec */
return
0
;
}
/*
** Look for a particular board name in the on-board EEPROM.
*/
static
void
EthwrkSignature
(
char
*
name
,
char
*
eeprom_image
)
{
unsigned
long
i
,
j
,
k
;
char
signatures
[][
EWRK3_NAME_LENGTH
]
=
EWRK3_SIGNATURE
;
strcpy
(
name
,
""
);
for
(
i
=
0
;
*
signatures
[
i
]
!=
'\0'
&&
*
name
==
'\0'
;
i
++
)
{
for
(
j
=
EEPROM_PNAME7
,
k
=
0
;
j
<=
EEPROM_PNAME0
&&
k
<
strlen
(
signatures
[
i
]);
j
++
)
{
if
(
signatures
[
i
][
k
]
==
eeprom_image
[
j
])
{
/* track signature */
k
++
;
}
else
{
/* lost signature; begin search again */
k
=
0
;
}
}
if
(
k
==
strlen
(
signatures
[
i
]))
{
for
(
k
=
0
;
k
<
EWRK3_NAME_LENGTH
;
k
++
)
{
name
[
k
]
=
eeprom_image
[
EEPROM_PNAME7
+
k
];
name
[
EWRK3_NAME_LENGTH
]
=
'\0'
;
}
}
}
return
;
/* return the device name string */
}
/*
** Look for a special sequence in the Ethernet station address PROM that
** is common across all EWRK3 products.
*/
static
int
DevicePresent
(
short
iobase
)
{
static
short
fp
=
1
,
sigLength
=
0
;
static
char
devSig
[]
=
PROBE_SEQUENCE
;
char
data
;
int
i
,
j
,
status
=
0
;
static
char
asc2hex
(
char
value
);
/*
** Convert the ascii signature to a hex equivalent & pack in place
*/
if
(
fp
)
{
/* only do this once!... */
for
(
i
=
0
,
j
=
0
;
devSig
[
i
]
!=
'\0'
&&
!
status
;
i
+=
2
,
j
++
)
{
if
((
devSig
[
i
]
=
asc2hex
(
devSig
[
i
]))
>=
0
)
{
devSig
[
i
]
<<=
4
;
if
((
devSig
[
i
+
1
]
=
asc2hex
(
devSig
[
i
+
1
]))
>=
0
){
devSig
[
j
]
=
devSig
[
i
]
+
devSig
[
i
+
1
];
}
else
{
status
=
-
1
;
}
}
else
{
status
=
-
1
;
}
}
sigLength
=
j
;
fp
=
0
;
}
/*
** Search the Ethernet address ROM for the signature. Since the ROM address
** counter can start at an arbitrary point, the search must include the entire
** probe sequence length plus the (length_of_the_signature - 1).
** Stop the search IMMEDIATELY after the signature is found so that the
** PROM address counter is correctly positioned at the start of the
** ethernet address for later read out.
*/
if
(
!
status
)
{
for
(
i
=
0
,
j
=
0
;
j
<
sigLength
&&
i
<
PROBE_LENGTH
+
sigLength
-
1
;
i
++
)
{
data
=
inb
(
EWRK3_APROM
);
if
(
devSig
[
j
]
==
data
)
{
/* track signature */
j
++
;
}
else
{
/* lost signature; begin search again */
j
=
0
;
}
}
if
(
j
!=
sigLength
)
{
status
=
-
ENODEV
;
/* search failed */
}
}
return
status
;
}
static
unsigned
char
aprom_crc
(
struct
device
*
dev
,
unsigned
char
*
eeprom_image
,
char
chipType
)
{
long
k
;
unsigned
short
j
,
chksum
;
unsigned
char
crc
,
lfsr
,
sd
,
status
=
0
;
int
iobase
=
dev
->
base_addr
;
if
(
chipType
==
LeMAC2
)
{
for
(
crc
=
0x6a
,
j
=
0
;
j
<
ETH_ALEN
;
j
++
)
{
for
(
sd
=
inb
(
EWRK3_PAR0
+
j
),
k
=
0
;
k
<
8
;
k
++
,
sd
>>=
1
)
{
lfsr
=
((((
crc
&
0x02
)
>>
1
)
^
(
crc
&
0x01
))
^
(
sd
&
0x01
))
<<
7
;
crc
=
(
crc
>>
1
)
+
lfsr
;
}
}
if
(
crc
!=
eeprom_image
[
EEPROM_PA_CRC
])
status
=
-
1
;
}
else
{
for
(
k
=
0
,
j
=
0
;
j
<
3
;
j
++
)
{
k
<<=
1
;
if
(
k
>
0xffff
)
k
-=
0xffff
;
k
+=
inw
(
EWRK3_PAR0
+
(
j
<<
1
));
if
(
k
>
0xffff
)
k
-=
0xffff
;
}
if
(
k
==
0xffff
)
k
=
0
;
chksum
=
inb
(
EWRK3_APROM
);
chksum
|=
(
inb
(
EWRK3_APROM
)
<<
8
);
if
(
k
!=
chksum
)
status
=
-
1
;
}
return
status
;
}
/*
** Perform IOCTL call functions here. Some are privileged operations and the
** effective uid is checked in those cases.
*/
static
int
ewrk3_ioctl
(
struct
device
*
dev
,
struct
ifreq
*
rq
)
{
struct
ewrk3_private
*
lp
=
(
struct
ewrk3_private
*
)
dev
->
priv
;
struct
ewrk3_ioctl
*
ioc
=
(
struct
ewrk3_ioctl
*
)
&
rq
->
ifr_data
;
int
i
,
j
,
iobase
=
dev
->
base_addr
,
status
=
0
;
unsigned
char
csr
;
union
{
unsigned
char
addr
[
HASH_TABLE_LEN
*
ETH_ALEN
];
unsigned
short
val
[(
HASH_TABLE_LEN
*
ETH_ALEN
)
>>
1
];
}
tmp
;
switch
(
ioc
->
cmd
)
{
case
EWRK3_GET_HWADDR
:
/* Get the hardware address */
for
(
i
=
0
;
i
<
ETH_ALEN
;
i
++
)
{
tmp
.
addr
[
i
]
=
dev
->
dev_addr
[
i
];
}
ioc
->
len
=
ETH_ALEN
;
memcpy_tofs
(
ioc
->
data
,
tmp
.
addr
,
ioc
->
len
);
break
;
case
EWRK3_SET_HWADDR
:
/* Set the hardware address */
if
(
suser
())
{
csr
=
inb
(
EWRK3_CSR
);
csr
|=
(
TXD
|
RXD
);
outb
(
csr
,
EWRK3_CSR
);
/* Disable the TX and RX */
memcpy_fromfs
(
tmp
.
addr
,
ioc
->
data
,
ETH_ALEN
);
for
(
i
=
0
;
i
<
ETH_ALEN
;
i
++
)
{
dev
->
dev_addr
[
i
]
=
tmp
.
addr
[
i
];
outb
(
tmp
.
addr
[
i
],
EWRK3_PAR0
+
i
);
}
csr
&=
~
(
TXD
|
RXD
);
/* Enable the TX and RX */
outb
(
csr
,
EWRK3_CSR
);
}
else
{
status
=
-
EPERM
;
}
break
;
case
EWRK3_SET_PROM
:
/* Set Promiscuous Mode */
if
(
suser
())
{
csr
=
inb
(
EWRK3_CSR
);
csr
|=
PME
;
csr
&=
~
MCE
;
outb
(
csr
,
EWRK3_CSR
);
}
else
{
status
=
-
EPERM
;
}
break
;
case
EWRK3_CLR_PROM
:
/* Clear Promiscuous Mode */
if
(
suser
())
{
csr
=
inb
(
EWRK3_CSR
);
csr
&=
~
PME
;
outb
(
csr
,
EWRK3_CSR
);
}
else
{
status
=
-
EPERM
;
}
break
;
case
EWRK3_SAY_BOO
:
/* Say "Boo!" to the kernel log file */
printk
(
"%s: Boo!
\n
"
,
dev
->
name
);
break
;
case
EWRK3_GET_MCA
:
/* Get the multicast address table */
while
(
set_bit
(
0
,
(
void
*
)
&
lp
->
lock
)
!=
0
);
/* Wait for lock to free */
if
(
lp
->
shmem_length
==
IO_ONLY
)
{
outb
(
0
,
EWRK3_IOPR
);
outw
(
PAGE0_HTE
,
EWRK3_PIR1
);
for
(
i
=
0
;
i
<
(
HASH_TABLE_LEN
>>
3
);
i
++
)
{
tmp
.
addr
[
i
]
=
inb
(
EWRK3_DATA
);
}
}
else
{
outb
(
0
,
EWRK3_MPR
);
memcpy
(
tmp
.
addr
,
(
char
*
)(
lp
->
shmem_base
+
PAGE0_HTE
),
(
HASH_TABLE_LEN
>>
3
));
}
ioc
->
len
=
(
HASH_TABLE_LEN
>>
3
);
memcpy_tofs
(
ioc
->
data
,
tmp
.
addr
,
ioc
->
len
);
lp
->
lock
=
0
;
/* Unlock the page register */
break
;
case
EWRK3_SET_MCA
:
/* Set a multicast address */
if
(
suser
())
{
if
(
ioc
->
len
!=
HASH_TABLE_LEN
)
{
/* MCA changes */
memcpy_fromfs
(
tmp
.
addr
,
ioc
->
data
,
ETH_ALEN
*
ioc
->
len
);
}
set_multicast_list
(
dev
,
ioc
->
len
,
tmp
.
addr
);
}
else
{
status
=
-
EPERM
;
}
break
;
case
EWRK3_CLR_MCA
:
/* Clear all multicast addresses */
if
(
suser
())
{
set_multicast_list
(
dev
,
0
,
NULL
);
}
else
{
status
=
-
EPERM
;
}
break
;
case
EWRK3_MCA_EN
:
/* Enable multicast addressing */
if
(
suser
())
{
csr
=
inb
(
EWRK3_CSR
);
csr
|=
MCE
;
csr
&=
~
PME
;
outb
(
csr
,
EWRK3_CSR
);
}
else
{
status
=
-
EPERM
;
}
break
;
case
EWRK3_GET_STATS
:
/* Get the driver statistics */
cli
();
memcpy_tofs
(
ioc
->
data
,
&
lp
->
pktStats
,
sizeof
(
lp
->
pktStats
));
ioc
->
len
=
EWRK3_PKT_STAT_SZ
;
sti
();
break
;
case
EWRK3_CLR_STATS
:
/* Zero out the driver statistics */
if
(
suser
())
{
cli
();
memset
(
&
lp
->
pktStats
,
0
,
sizeof
(
lp
->
pktStats
));
sti
();
}
else
{
status
=
-
EPERM
;
}
break
;
case
EWRK3_GET_CSR
:
/* Get the CSR Register contents */
tmp
.
addr
[
0
]
=
inb
(
EWRK3_CSR
);
memcpy_tofs
(
ioc
->
data
,
tmp
.
addr
,
1
);
break
;
case
EWRK3_SET_CSR
:
/* Set the CSR Register contents */
if
(
suser
())
{
memcpy_fromfs
(
tmp
.
addr
,
ioc
->
data
,
1
);
outb
(
tmp
.
addr
[
0
],
EWRK3_CSR
);
}
else
{
status
=
-
EPERM
;
}
break
;
case
EWRK3_GET_EEPROM
:
/* Get the EEPROM contents */
if
(
suser
())
{
for
(
i
=
0
;
i
<
(
EEPROM_MAX
>>
1
);
i
++
)
{
tmp
.
val
[
i
]
=
(
short
)
Read_EEPROM
(
iobase
,
i
);
}
i
=
EEPROM_MAX
;
tmp
.
addr
[
i
++
]
=
inb
(
EWRK3_CMR
);
/* Config/Management Reg. */
for
(
j
=
0
;
j
<
ETH_ALEN
;
j
++
)
{
tmp
.
addr
[
i
++
]
=
inb
(
EWRK3_PAR0
+
j
);
}
ioc
->
len
=
EEPROM_MAX
+
1
+
ETH_ALEN
;
memcpy_tofs
(
ioc
->
data
,
tmp
.
addr
,
ioc
->
len
);
}
else
{
status
=
-
EPERM
;
}
break
;
case
EWRK3_SET_EEPROM
:
/* Set the EEPROM contents */
if
(
suser
())
{
memcpy_fromfs
(
tmp
.
addr
,
ioc
->
data
,
EEPROM_MAX
);
for
(
i
=
0
;
i
<
(
EEPROM_MAX
>>
1
);
i
++
)
{
Write_EEPROM
(
tmp
.
val
[
i
],
iobase
,
i
);
}
}
else
{
status
=
-
EPERM
;
}
break
;
case
EWRK3_GET_CMR
:
/* Get the CMR Register contents */
tmp
.
addr
[
0
]
=
inb
(
EWRK3_CMR
);
memcpy_tofs
(
ioc
->
data
,
tmp
.
addr
,
1
);
break
;
case
EWRK3_SET_TX_CUT_THRU
:
/* Set TX cut through mode */
if
(
suser
())
{
lp
->
txc
=
1
;
}
else
{
status
=
-
EPERM
;
}
break
;
case
EWRK3_CLR_TX_CUT_THRU
:
/* Clear TX cut through mode */
if
(
suser
())
{
lp
->
txc
=
0
;
}
else
{
status
=
-
EPERM
;
}
break
;
default:
status
=
-
EOPNOTSUPP
;
}
return
status
;
}
static
char
asc2hex
(
char
value
)
{
value
-=
0x30
;
/* normalise to 0..9 range */
if
(
value
>=
0
)
{
if
(
value
>
9
)
{
/* but may not be 10..15 */
value
&=
0x1f
;
/* make A..F & a..f be the same */
value
-=
0x07
;
/* normalise to 10..15 range */
if
((
value
<
0x0a
)
||
(
value
>
0x0f
))
{
/* if outside range then... */
value
=
-
1
;
/* ...signal error */
}
}
}
else
{
/* outside 0..9 range... */
value
=
-
1
;
/* ...signal error */
}
return
value
;
/* return hex char or error */
}
#ifdef MODULE
char
kernel_version
[]
=
UTS_RELEASE
;
static
struct
device
thisEthwrk
=
{
" "
,
/* device name inserted by /linux/drivers/net/net_init.c */
0
,
0
,
0
,
0
,
0x300
,
5
,
/* I/O address, IRQ <--- EDIT THIS LINE FOR YOUR CONFIGURATION */
0
,
0
,
0
,
NULL
,
ewrk3_probe
};
int
init_module
(
void
)
{
if
(
register_netdev
(
&
thisEthwrk
)
!=
0
)
return
-
EIO
;
return
0
;
}
void
cleanup_module
(
void
)
{
if
(
MOD_IN_USE
)
{
printk
(
"%s: device busy, remove delayed
\n
"
,
thisEthwrk
.
name
);
}
else
{
unregister_netdev
(
&
thisEthwrk
);
}
}
#endif
/* MODULE */
/*
* Local variables:
* kernel-compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c ewrk3.c"
*
* module-compile-command: "gcc -D__KERNEL__ -DMODULE -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -m486 -c ewrk3.c"
* End:
*/
drivers/net/ewrk3.h
0 → 100644
View file @
a6614639
/*
Written 1994 by David C. Davies.
Copyright 1994 Digital Equipment Corporation.
This software may be used and distributed according to the terms of the
GNU Public License, incorporated herein by reference.
The author may be reached as davies@wanton.lkg.dec.com or Digital
Equipment Corporation, 550 King Street, Littleton MA 01460.
=========================================================================
*/
/*
** I/O Address Register Map
*/
#define EWRK3_CSR iobase+0x00
/* Control and Status Register */
#define EWRK3_CR iobase+0x01
/* Control Register */
#define EWRK3_ICR iobase+0x02
/* Interrupt Control Register */
#define EWRK3_TSR iobase+0x03
/* Transmit Status Register */
#define EWRK3_RSVD1 iobase+0x04
/* RESERVED */
#define EWRK3_RSVD2 iobase+0x05
/* RESERVED */
#define EWRK3_FMQ iobase+0x06
/* Free Memory Queue */
#define EWRK3_FMQC iobase+0x07
/* Free Memory Queue Counter */
#define EWRK3_RQ iobase+0x08
/* Receive Queue */
#define EWRK3_RQC iobase+0x09
/* Receive Queue Counter */
#define EWRK3_TQ iobase+0x0a
/* Transmit Queue */
#define EWRK3_TQC iobase+0x0b
/* Transmit Queue Counter */
#define EWRK3_TDQ iobase+0x0c
/* Transmit Done Queue */
#define EWRK3_TDQC iobase+0x0d
/* Transmit Done Queue Counter */
#define EWRK3_PIR1 iobase+0x0e
/* Page Index Register 1 */
#define EWRK3_PIR2 iobase+0x0f
/* Page Index Register 2 */
#define EWRK3_DATA iobase+0x10
/* Data Register */
#define EWRK3_IOPR iobase+0x11
/* I/O Page Register */
#define EWRK3_IOBR iobase+0x12
/* I/O Base Register */
#define EWRK3_MPR iobase+0x13
/* Memory Page Register */
#define EWRK3_MBR iobase+0x14
/* Memory Base Register */
#define EWRK3_APROM iobase+0x15
/* Address PROM */
#define EWRK3_EPROM1 iobase+0x16
/* EEPROM Data Register 1 */
#define EWRK3_EPROM2 iobase+0x17
/* EEPROM Data Register 2 */
#define EWRK3_PAR0 iobase+0x18
/* Physical Address Register 0 */
#define EWRK3_PAR1 iobase+0x19
/* Physical Address Register 1 */
#define EWRK3_PAR2 iobase+0x1a
/* Physical Address Register 2 */
#define EWRK3_PAR3 iobase+0x1b
/* Physical Address Register 3 */
#define EWRK3_PAR4 iobase+0x1c
/* Physical Address Register 4 */
#define EWRK3_PAR5 iobase+0x1d
/* Physical Address Register 5 */
#define EWRK3_CMR iobase+0x1e
/* Configuration/Management Register */
/*
** Control Page Map
*/
#define PAGE0_FMQ 0x000
/* Free Memory Queue */
#define PAGE0_RQ 0x080
/* Receive Queue */
#define PAGE0_TQ 0x100
/* Transmit Queue */
#define PAGE0_TDQ 0x180
/* Transmit Done Queue */
#define PAGE0_HTE 0x200
/* Hash Table Entries */
#define PAGE0_RSVD 0x240
/* RESERVED */
#define PAGE0_USRD 0x600
/* User Data */
/*
** Control and Status Register bit definitions (EWRK3_CSR)
*/
#define RA 0x80
/* Runt Accept */
#define PME 0x40
/* Promiscuous Mode Enable */
#define MCE 0x20
/* Multicast Enable */
#define TNE 0x08
/* TX Done Queue Not Empty */
#define RNE 0x04
/* RX Queue Not Empty */
#define TXD 0x02
/* TX Disable */
#define RXD 0x01
/* RX Disable */
/*
** Control Register bit definitions (EWRK3_CR)
*/
#define APD 0x80
/* Auto Port Disable */
#define PSEL 0x40
/* Port Select (0->TP port) */
#define LBCK 0x20
/* LoopBaCK enable */
#define FDUP 0x10
/* Full DUPlex enable */
#define FBUS 0x08
/* Fast BUS enable (ISA clk > 8.33MHz) */
#define EN_16 0x04
/* ENable 16 bit memory accesses */
#define LED 0x02
/* LED (1-> turn on) */
/*
** Interrupt Control Register bit definitions (EWRK3_ICR)
*/
#define IE 0x80
/* Interrupt Enable */
#define IS 0x60
/* Interrupt Selected */
#define TNEM 0x08
/* TNE Mask (0->mask) */
#define RNEM 0x04
/* RNE Mask (0->mask) */
#define TXDM 0x02
/* TXD Mask (0->mask) */
#define RXDM 0x01
/* RXD Mask (0->mask) */
/*
** Transmit Status Register bit definitions (EWRK3_TSR)
*/
#define NCL 0x80
/* No Carrier Loopback */
#define ID 0x40
/* Initially Deferred */
#define LCL 0x20
/* Late CoLlision */
#define ECL 0x10
/* Excessive CoLlisions */
#define RCNTR 0x0f
/* Retries CouNTeR */
/*
** I/O Page Register bit definitions (EWRK3_IOPR)
*/
#define EEPROM_INIT 0xc0
/* EEPROM INIT command */
#define EEPROM_WR_EN 0xc8
/* EEPROM WRITE ENABLE command */
#define EEPROM_WR 0xd0
/* EEPROM WRITE command */
#define EEPROM_WR_DIS 0xd8
/* EEPROM WRITE DISABLE command */
#define EEPROM_RD 0xe0
/* EEPROM READ command */
/*
** I/O Base Register bit definitions (EWRK3_IOBR)
*/
#define EISA 0x20
/* Enable EISA ID and Control Registers */
#define IOB 0x1f
/* Compare bits for I/O Base Address */
/*
** I/O Congiguration/Management Register bit definitions (EWRK3_CMR)
*/
#define RA 0x80
/* Read Ahead */
#define WB 0x40
/* Write Behind */
#define LINK 0x20
/* 0->TP */
#define POLARITY 0x10
/* Informational */
#define NO_EEPROM 0x0c
/* NO_EEPROM<1:0> pin status */
#define HS 0x08
/* Hard Strapped pin status (LeMAC2) */
#define PNP 0x04
/* Plug 'n Play */
#define DRAM 0x02
/* 0-> 1DRAM, 1-> 2 DRAM on board */
#define _0WS 0x01
/* Zero Wait State */
/*
** MAC Receive Status Register bit definitions
*/
#define ROK 0x80
/* Receive OK summary */
#define IAM 0x10
/* Individual Address Match */
#define MCM 0x08
/* MultiCast Match */
#define DBE 0x04
/* Dribble Bit Error */
#define CRC 0x02
/* CRC error */
#define PLL 0x01
/* Phase Lock Lost */
/*
** MAC Transmit Control Register bit definitions
*/
#define SQEE 0x40
/* SQE Enable - look for heartbeat */
#define SED 0x20
/* Stop when Error Detected */
#define QMODE 0x10
/* Q_MODE */
#define LAB 0x08
/* Less Aggressive Backoff */
#define PAD 0x04
/* PAD Runt Packets */
#define IFC 0x02
/* Insert Frame Check */
#define ISA 0x01
/* Insert Source Address */
/*
** MAC Transmit Status Register bit definitions
*/
#define VSTS 0x80
/* Valid STatuS */
#define MAC_CTU 0x40
/* Cut Through Used */
#define MAC_SQE 0x20
/* Signal Quality Error */
#define MAC_NCL 0x10
/* No Carrier Loopback */
#define MAC_LCL 0x08
/* Late Collision */
#define MAC_ID 0x04
/* Initially Deferred */
#define MAC_COLL 0x03
/* COLLision status */
#define MAC_XCOLL 0x03
/* Excessive Collisions */
#define MAC_MCOLL 0x02
/* Multiple Collisions */
#define MAC_OCOLL 0x01
/* One Collision */
#define MAC_NOCOLL 0x00
/* No Collisions */
#define MAC_XUR 0x03
/* Excessive Underruns */
#define MAC_TXE 0x7f
/* TX Errors */
/*
** EISA Configuration Register bit definitions
*/
#define EISA_ID0 iobase + 0x0c80
/* EISA ID Register 0 */
#define EISA_ID1 iobase + 0x0c81
/* EISA ID Register 1 */
#define EISA_ID2 iobase + 0x0c82
/* EISA ID Register 2 */
#define EISA_ID3 iobase + 0x0c83
/* EISA ID Register 3 */
#define EISA_CR iobase + 0x0c84
/* EISA Control Register */
/*
** EEPROM BYTES
*/
#define EEPROM_MEMB 0x00
#define EEPROM_IOB 0x01
#define EEPROM_EISA_ID0 0x02
#define EEPROM_EISA_ID1 0x03
#define EEPROM_EISA_ID2 0x04
#define EEPROM_EISA_ID3 0x05
#define EEPROM_MISC0 0x06
#define EEPROM_MISC1 0x07
#define EEPROM_PNAME7 0x08
#define EEPROM_PNAME6 0x09
#define EEPROM_PNAME5 0x0a
#define EEPROM_PNAME4 0x0b
#define EEPROM_PNAME3 0x0c
#define EEPROM_PNAME2 0x0d
#define EEPROM_PNAME1 0x0e
#define EEPROM_PNAME0 0x0f
#define EEPROM_SWFLAGS 0x10
#define EEPROM_HWCAT 0x11
#define EEPROM_NETMAN2 0x12
#define EEPROM_REVLVL 0x13
#define EEPROM_NETMAN0 0x14
#define EEPROM_NETMAN1 0x15
#define EEPROM_CHIPVER 0x16
#define EEPROM_SETUP 0x17
#define EEPROM_PADDR0 0x18
#define EEPROM_PADDR1 0x19
#define EEPROM_PADDR2 0x1a
#define EEPROM_PADDR3 0x1b
#define EEPROM_PADDR4 0x1c
#define EEPROM_PADDR5 0x1d
#define EEPROM_PA_CRC 0x1e
#define EEPROM_CHKSUM 0x1f
/*
** EEPROM bytes for checksumming
*/
#define EEPROM_MAX 32
/* bytes */
/*
** EEPROM MISCELLANEOUS FLAGS
*/
#define RBE_SHADOW 0x0100
/* Remote Boot Enable Shadow */
#define READ_AHEAD 0x0080
/* Read Ahead feature */
#define IRQ_SEL2 0x0070
/* IRQ line selection (LeMAC2) */
#define IRQ_SEL 0x0060
/* IRQ line selection */
#define FAST_BUS 0x0008
/* ISA Bus speeds > 8.33MHz */
#define ENA_16 0x0004
/* Enables 16 bit memory transfers */
#define WRITE_BEHIND 0x0002
/* Write Behind feature */
#define _0WS_ENA 0x0001
/* Zero Wait State Enable */
/*
** EEPROM NETWORK MANAGEMENT FLAGS
*/
#define NETMAN_POL 0x04
/* Polarity defeat */
#define NETMAN_LINK 0x02
/* Link defeat */
#define NETMAN_CCE 0x01
/* Custom Counters Enable */
/*
** EEPROM SW FLAGS
*/
#define SW_SQE 0x10
/* Signal Quality Error */
#define SW_LAB 0x08
/* Less Aggressive Backoff */
#define SW_INIT 0x04
/* Initialized */
#define SW_TIMEOUT 0x02
/* 0:2.5 mins, 1: 30 secs */
#define SW_REMOTE 0x01
/* Remote Boot Enable -> 1 */
/*
** EEPROM SETUP FLAGS
*/
#define SETUP_APD 0x80
/* AutoPort Disable */
#define SETUP_PS 0x40
/* Port Select */
#define SETUP_MP 0x20
/* MultiPort */
#define SETUP_1TP 0x10
/* 1 port, TP */
#define SETUP_1COAX 0x00
/* 1 port, Coax */
#define SETUP_DRAM 0x02
/* Number of DRAMS on board */
/*
** EEPROM MANAGEMENT FLAGS
*/
#define MGMT_CCE 0x01
/* Custom Counters Enable */
/*
** EEPROM VERSIONS
*/
#define LeMAC 0x11
#define LeMAC2 0x12
/*
** Miscellaneous
*/
#define EEPROM_WAIT_TIME 1000
/* Number of microseconds */
#define EISA_EN 0x0001
/* Enable EISA bus buffers */
#define HASH_TABLE_LEN 512
/* Bits */
#define XCT 0x80
/* Transmit Cut Through */
#define PRELOAD 16
/* 4 long words */
#define MASK_INTERRUPTS 1
#define UNMASK_INTERRUPTS 0
/*
** Include the IOCTL stuff
*/
#include <linux/sockios.h>
#define EWRK3IOCTL SIOCDEVPRIVATE
struct
ewrk3_ioctl
{
unsigned
short
cmd
;
/* Command to run */
unsigned
short
len
;
/* Length of the data buffer */
unsigned
char
*
data
;
/* Pointer to the data buffer */
};
/*
** Recognised commands for the driver
*/
#define EWRK3_GET_HWADDR 0x01
/* Get the hardware address */
#define EWRK3_SET_HWADDR 0x02
/* Get the hardware address */
#define EWRK3_SET_PROM 0x03
/* Set Promiscuous Mode */
#define EWRK3_CLR_PROM 0x04
/* Clear Promiscuous Mode */
#define EWRK3_SAY_BOO 0x05
/* Say "Boo!" to the kernel log file */
#define EWRK3_GET_MCA 0x06
/* Get a multicast address */
#define EWRK3_SET_MCA 0x07
/* Set a multicast address */
#define EWRK3_CLR_MCA 0x08
/* Clear a multicast address */
#define EWRK3_MCA_EN 0x09
/* Enable a multicast address group */
#define EWRK3_GET_STATS 0x0a
/* Get the driver statistics */
#define EWRK3_CLR_STATS 0x0b
/* Zero out the driver statistics */
#define EWRK3_GET_CSR 0x0c
/* Get the CSR Register contents */
#define EWRK3_SET_CSR 0x0d
/* Set the CSR Register contents */
#define EWRK3_GET_EEPROM 0x0e
/* Get the EEPROM contents */
#define EWRK3_SET_EEPROM 0x0f
/* Set the EEPROM contents */
#define EWRK3_GET_CMR 0x10
/* Get the CMR Register contents */
#define EWRK3_CLR_TX_CUT_THRU 0x11
/* Clear the TX cut through mode */
#define EWRK3_SET_TX_CUT_THRU 0x12
/* Set the TX cut through mode */
fs/block_dev.c
View file @
a6614639
...
@@ -24,7 +24,7 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
...
@@ -24,7 +24,7 @@ int block_write(struct inode * inode, struct file * filp, char * buf, int count)
loff_t
offset
;
loff_t
offset
;
int
chars
;
int
chars
;
int
written
=
0
;
int
written
=
0
;
int
cluster_list
[
4
];
int
cluster_list
[
8
];
struct
buffer_head
*
bhlist
[
NBUF
];
struct
buffer_head
*
bhlist
[
NBUF
];
int
blocks_per_cluster
;
int
blocks_per_cluster
;
unsigned
int
size
;
unsigned
int
size
;
...
@@ -159,7 +159,7 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count)
...
@@ -159,7 +159,7 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count)
int
blocksize_bits
,
i
;
int
blocksize_bits
,
i
;
unsigned
int
blocks
,
rblocks
,
left
;
unsigned
int
blocks
,
rblocks
,
left
;
int
bhrequest
,
uptodate
;
int
bhrequest
,
uptodate
;
int
cluster_list
[
4
];
int
cluster_list
[
8
];
int
blocks_per_cluster
;
int
blocks_per_cluster
;
struct
buffer_head
**
bhb
,
**
bhe
;
struct
buffer_head
**
bhb
,
**
bhe
;
struct
buffer_head
*
buflist
[
NBUF
];
struct
buffer_head
*
buflist
[
NBUF
];
...
...
fs/minix/inode.c
View file @
a6614639
...
@@ -122,6 +122,7 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
...
@@ -122,6 +122,7 @@ struct super_block *minix_read_super(struct super_block *s,void *data,
if
(
32
!=
sizeof
(
struct
minix_inode
))
if
(
32
!=
sizeof
(
struct
minix_inode
))
panic
(
"bad i-node size"
);
panic
(
"bad i-node size"
);
lock_super
(
s
);
lock_super
(
s
);
set_blocksize
(
dev
,
BLOCK_SIZE
);
if
(
!
(
bh
=
bread
(
dev
,
1
,
BLOCK_SIZE
)))
{
if
(
!
(
bh
=
bread
(
dev
,
1
,
BLOCK_SIZE
)))
{
s
->
s_dev
=
0
;
s
->
s_dev
=
0
;
unlock_super
(
s
);
unlock_super
(
s
);
...
...
fs/msdos/fat.c
View file @
a6614639
...
@@ -20,7 +20,6 @@ int fat_access(struct super_block *sb,int nr,int new_value)
...
@@ -20,7 +20,6 @@ int fat_access(struct super_block *sb,int nr,int new_value)
{
{
struct
buffer_head
*
bh
,
*
bh2
,
*
c_bh
,
*
c_bh2
;
struct
buffer_head
*
bh
,
*
bh2
,
*
c_bh
,
*
c_bh2
;
unsigned
char
*
p_first
,
*
p_last
;
unsigned
char
*
p_first
,
*
p_last
;
void
*
data
,
*
data2
,
*
c_data
,
*
c_data2
;
int
first
,
last
,
next
,
copy
;
int
first
,
last
,
next
,
copy
;
if
((
unsigned
)
(
nr
-
2
)
>=
MSDOS_SB
(
sb
)
->
clusters
)
return
0
;
if
((
unsigned
)
(
nr
-
2
)
>=
MSDOS_SB
(
sb
)
->
clusters
)
return
0
;
...
@@ -30,17 +29,15 @@ int fat_access(struct super_block *sb,int nr,int new_value)
...
@@ -30,17 +29,15 @@ int fat_access(struct super_block *sb,int nr,int new_value)
last
=
first
+
1
;
last
=
first
+
1
;
}
}
if
(
!
(
bh
=
msdos_sread
(
sb
->
s_dev
,
MSDOS_SB
(
sb
)
->
fat_start
+
(
first
>>
if
(
!
(
bh
=
msdos_sread
(
sb
->
s_dev
,
MSDOS_SB
(
sb
)
->
fat_start
+
(
first
>>
SECTOR_BITS
)
,
&
data
)))
{
SECTOR_BITS
))))
{
printk
(
"bread in fat_access failed
\n
"
);
printk
(
"bread in fat_access failed
\n
"
);
return
0
;
return
0
;
}
}
if
((
first
>>
SECTOR_BITS
)
==
(
last
>>
SECTOR_BITS
))
{
if
((
first
>>
SECTOR_BITS
)
==
(
last
>>
SECTOR_BITS
))
bh2
=
bh
;
bh2
=
bh
;
data2
=
data
;
}
else
{
else
{
if
(
!
(
bh2
=
msdos_sread
(
sb
->
s_dev
,
MSDOS_SB
(
sb
)
->
fat_start
+
(
last
if
(
!
(
bh2
=
msdos_sread
(
sb
->
s_dev
,
MSDOS_SB
(
sb
)
->
fat_start
+
(
last
>>
SECTOR_BITS
)
,
&
data2
)))
{
>>
SECTOR_BITS
))))
{
brelse
(
bh
);
brelse
(
bh
);
printk
(
"bread in fat_access failed
\n
"
);
printk
(
"bread in fat_access failed
\n
"
);
return
0
;
return
0
;
...
@@ -48,13 +45,13 @@ int fat_access(struct super_block *sb,int nr,int new_value)
...
@@ -48,13 +45,13 @@ int fat_access(struct super_block *sb,int nr,int new_value)
}
}
if
(
MSDOS_SB
(
sb
)
->
fat_bits
==
16
)
{
if
(
MSDOS_SB
(
sb
)
->
fat_bits
==
16
)
{
p_first
=
p_last
=
NULL
;
/* GCC needs that stuff */
p_first
=
p_last
=
NULL
;
/* GCC needs that stuff */
next
=
CF_LE_W
(((
unsigned
short
*
)
data
)[(
first
&
next
=
CF_LE_W
(((
unsigned
short
*
)
bh
->
b_
data
)[(
first
&
(
SECTOR_SIZE
-
1
))
>>
1
]);
(
SECTOR_SIZE
-
1
))
>>
1
]);
if
(
next
>=
0xfff7
)
next
=
-
1
;
if
(
next
>=
0xfff7
)
next
=
-
1
;
}
}
else
{
else
{
p_first
=
&
((
unsigned
char
*
)
data
)[
first
&
(
SECTOR_SIZE
-
1
)];
p_first
=
&
((
unsigned
char
*
)
bh
->
b_
data
)[
first
&
(
SECTOR_SIZE
-
1
)];
p_last
=
&
((
unsigned
char
*
)
data2
)[(
first
+
1
)
&
p_last
=
&
((
unsigned
char
*
)
bh2
->
b_data
)[(
first
+
1
)
&
(
SECTOR_SIZE
-
1
)];
(
SECTOR_SIZE
-
1
)];
if
(
nr
&
1
)
next
=
((
*
p_first
>>
4
)
|
(
*
p_last
<<
4
))
&
0xfff
;
if
(
nr
&
1
)
next
=
((
*
p_first
>>
4
)
|
(
*
p_last
<<
4
))
&
0xfff
;
else
next
=
(
*
p_first
+
(
*
p_last
<<
8
))
&
0xfff
;
else
next
=
(
*
p_first
+
(
*
p_last
<<
8
))
&
0xfff
;
...
@@ -62,7 +59,7 @@ int fat_access(struct super_block *sb,int nr,int new_value)
...
@@ -62,7 +59,7 @@ int fat_access(struct super_block *sb,int nr,int new_value)
}
}
if
(
new_value
!=
-
1
)
{
if
(
new_value
!=
-
1
)
{
if
(
MSDOS_SB
(
sb
)
->
fat_bits
==
16
)
if
(
MSDOS_SB
(
sb
)
->
fat_bits
==
16
)
((
unsigned
short
*
)
data
)[(
first
&
(
SECTOR_SIZE
-
1
))
>>
((
unsigned
short
*
)
bh
->
b_
data
)[(
first
&
(
SECTOR_SIZE
-
1
))
>>
1
]
=
CT_LE_W
(
new_value
);
1
]
=
CT_LE_W
(
new_value
);
else
{
else
{
if
(
nr
&
1
)
{
if
(
nr
&
1
)
{
...
@@ -79,25 +76,25 @@ int fat_access(struct super_block *sb,int nr,int new_value)
...
@@ -79,25 +76,25 @@ int fat_access(struct super_block *sb,int nr,int new_value)
for
(
copy
=
1
;
copy
<
MSDOS_SB
(
sb
)
->
fats
;
copy
++
)
{
for
(
copy
=
1
;
copy
<
MSDOS_SB
(
sb
)
->
fats
;
copy
++
)
{
if
(
!
(
c_bh
=
msdos_sread
(
sb
->
s_dev
,
MSDOS_SB
(
sb
)
->
if
(
!
(
c_bh
=
msdos_sread
(
sb
->
s_dev
,
MSDOS_SB
(
sb
)
->
fat_start
+
(
first
>>
SECTOR_BITS
)
+
MSDOS_SB
(
sb
)
->
fat_start
+
(
first
>>
SECTOR_BITS
)
+
MSDOS_SB
(
sb
)
->
fat_length
*
copy
,
&
c_data
)))
break
;
fat_length
*
copy
)))
break
;
memcpy
(
c_
data
,
data
,
SECTOR_SIZE
);
memcpy
(
c_
bh
->
b_data
,
bh
->
b_
data
,
SECTOR_SIZE
);
mark_buffer_dirty
(
c_bh
,
1
);
mark_buffer_dirty
(
c_bh
,
1
);
if
(
data
!=
data2
||
bh
!=
bh2
)
{
if
(
bh
!=
bh2
)
{
if
(
!
(
c_bh2
=
msdos_sread
(
sb
->
s_dev
,
if
(
!
(
c_bh2
=
msdos_sread
(
sb
->
s_dev
,
MSDOS_SB
(
sb
)
->
fat_start
+
(
first
>>
MSDOS_SB
(
sb
)
->
fat_start
+
(
first
>>
SECTOR_BITS
)
+
MSDOS_SB
(
sb
)
->
fat_length
*
copy
SECTOR_BITS
)
+
MSDOS_SB
(
sb
)
->
fat_length
*
copy
+
1
,
&
c_data2
)))
{
+
1
)))
{
brelse
(
c_bh
);
brelse
(
c_bh
);
break
;
break
;
}
}
memcpy
(
c_
data2
,
data2
,
SECTOR_SIZE
);
memcpy
(
c_
bh2
->
b_data
,
bh2
->
b_data
,
SECTOR_SIZE
);
brelse
(
c_bh2
);
brelse
(
c_bh2
);
}
}
brelse
(
c_bh
);
brelse
(
c_bh
);
}
}
}
}
brelse
(
bh
);
brelse
(
bh
);
if
(
data
!=
data
2
)
brelse
(
bh2
);
if
(
bh
!=
bh
2
)
brelse
(
bh2
);
return
next
;
return
next
;
}
}
...
...
fs/msdos/file.c
View file @
a6614639
...
@@ -30,7 +30,7 @@ static struct file_operations msdos_file_operations = {
...
@@ -30,7 +30,7 @@ static struct file_operations msdos_file_operations = {
NULL
,
/* readdir - bad */
NULL
,
/* readdir - bad */
NULL
,
/* select - default */
NULL
,
/* select - default */
NULL
,
/* ioctl - default */
NULL
,
/* ioctl - default */
generic_mmap
,
/* mmap */
generic_mmap
,
/* mmap */
NULL
,
/* no special open is needed */
NULL
,
/* no special open is needed */
NULL
,
/* release */
NULL
,
/* release */
file_fsync
/* fsync */
file_fsync
/* fsync */
...
@@ -52,7 +52,7 @@ struct inode_operations msdos_file_inode_operations = {
...
@@ -52,7 +52,7 @@ struct inode_operations msdos_file_inode_operations = {
msdos_bmap
,
/* bmap */
msdos_bmap
,
/* bmap */
msdos_truncate
,
/* truncate */
msdos_truncate
,
/* truncate */
NULL
,
/* permission */
NULL
,
/* permission */
NULL
/* smap */
NULL
/* smap */
};
};
/*
/*
...
@@ -127,12 +127,11 @@ int msdos_file_read(
...
@@ -127,12 +127,11 @@ int msdos_file_read(
int
sector
;
int
sector
;
if
(
!
(
sector
=
msdos_smap
(
inode
,
filp
->
f_pos
>>
SECTOR_BITS
)))
if
(
!
(
sector
=
msdos_smap
(
inode
,
filp
->
f_pos
>>
SECTOR_BITS
)))
break
;
break
;
if
(
!
(
bh
=
msdos_sread
(
inode
->
i_dev
,
sector
,
&
data
)))
if
(
!
(
bh
=
msdos_sread
(
inode
->
i_dev
,
sector
)))
break
;
break
;
}
else
{
}
else
{
bh
=
pre
.
bhlist
[
pre
.
nolist
];
bh
=
pre
.
bhlist
[
pre
.
nolist
];
pre
.
bhlist
[
pre
.
nolist
++
]
=
NULL
;
pre
.
bhlist
[
pre
.
nolist
++
]
=
NULL
;
data
=
bh
->
b_data
;
wait_on_buffer
(
bh
);
wait_on_buffer
(
bh
);
if
(
!
bh
->
b_uptodate
){
if
(
!
bh
->
b_uptodate
){
/* read error ? */
/* read error ? */
...
@@ -140,6 +139,7 @@ int msdos_file_read(
...
@@ -140,6 +139,7 @@ int msdos_file_read(
break
;
break
;
}
}
}
}
data
=
bh
->
b_data
;
offset
=
filp
->
f_pos
&
(
SECTOR_SIZE
-
1
);
offset
=
filp
->
f_pos
&
(
SECTOR_SIZE
-
1
);
filp
->
f_pos
+=
(
size
=
MIN
(
SECTOR_SIZE
-
offset
,
left
));
filp
->
f_pos
+=
(
size
=
MIN
(
SECTOR_SIZE
-
offset
,
left
));
if
(
MSDOS_I
(
inode
)
->
i_binary
)
{
if
(
MSDOS_I
(
inode
)
->
i_binary
)
{
...
@@ -183,7 +183,6 @@ int msdos_file_write(
...
@@ -183,7 +183,6 @@ int msdos_file_write(
int
error
,
carry
;
int
error
,
carry
;
char
*
start
,
*
to
,
ch
;
char
*
start
,
*
to
,
ch
;
struct
buffer_head
*
bh
;
struct
buffer_head
*
bh
;
void
*
data
;
int
binary_mode
=
MSDOS_I
(
inode
)
->
i_binary
;
int
binary_mode
=
MSDOS_I
(
inode
)
->
i_binary
;
if
(
!
inode
)
{
if
(
!
inode
)
{
...
@@ -211,25 +210,28 @@ int msdos_file_write(
...
@@ -211,25 +210,28 @@ int msdos_file_write(
}
}
offset
=
filp
->
f_pos
&
(
SECTOR_SIZE
-
1
);
offset
=
filp
->
f_pos
&
(
SECTOR_SIZE
-
1
);
size
=
MIN
(
SECTOR_SIZE
-
offset
,
MAX
(
carry
,
count
));
size
=
MIN
(
SECTOR_SIZE
-
offset
,
MAX
(
carry
,
count
));
if
(
binary_mode
&&
offset
==
0
&&
size
==
SECTOR_SIZE
){
if
(
binary_mode
&&
offset
==
0
&&
(
size
==
SECTOR_SIZE
||
filp
->
f_pos
+
size
>=
inode
->
i_size
)){
/* No need to read the block first since we will */
/* No need to read the block first since we will */
/* completely overwrite it */
/* completely overwrite it */
/* or at least write past the end of file */
if
(
!
(
bh
=
getblk
(
inode
->
i_dev
,
sector
,
SECTOR_SIZE
))){
if
(
!
(
bh
=
getblk
(
inode
->
i_dev
,
sector
,
SECTOR_SIZE
))){
error
=
-
EIO
;
error
=
-
EIO
;
break
;
break
;
}
}
data
=
bh
->
b_data
;
}
else
if
(
!
(
bh
=
msdos_sread
(
inode
->
i_dev
,
sector
)))
{
}
else
if
(
!
(
bh
=
msdos_sread
(
inode
->
i_dev
,
sector
,
&
data
)))
{
error
=
-
EIO
;
error
=
-
EIO
;
break
;
break
;
}
}
if
(
binary_mode
)
{
if
(
binary_mode
)
{
memcpy_fromfs
(
data
+
offset
,
buf
,
written
=
size
);
memcpy_fromfs
(
bh
->
b_
data
+
offset
,
buf
,
written
=
size
);
buf
+=
size
;
buf
+=
size
;
}
}
else
{
else
{
written
=
left
=
SECTOR_SIZE
-
offset
;
written
=
left
=
SECTOR_SIZE
-
offset
;
to
=
(
char
*
)
data
+
(
filp
->
f_pos
&
(
SECTOR_SIZE
-
1
));
to
=
(
char
*
)
bh
->
b_
data
+
(
filp
->
f_pos
&
(
SECTOR_SIZE
-
1
));
if
(
carry
)
{
if
(
carry
)
{
*
to
++
=
'\n'
;
*
to
++
=
'\n'
;
left
--
;
left
--
;
...
...
fs/msdos/inode.c
View file @
a6614639
...
@@ -172,20 +172,7 @@ struct super_block *msdos_read_super(struct super_block *s,void *data,
...
@@ -172,20 +172,7 @@ struct super_block *msdos_read_super(struct super_block *s,void *data,
}
}
cache_init
();
cache_init
();
lock_super
(
s
);
lock_super
(
s
);
if
(
MAJOR
(
s
->
s_dev
)
==
FLOPPY_MAJOR
){
set_blocksize
(
s
->
s_dev
,
SECTOR_SIZE
);
/* Patch for floppy which lacks a table ??? */
static
int
tbdef
[]
=
{
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
1024
,
};
blksize_size
[
FLOPPY_MAJOR
]
=
tbdef
;
}
set_blocksize
(
s
->
s_dev
,
SECTOR_SIZE
);
bh
=
bread
(
s
->
s_dev
,
0
,
SECTOR_SIZE
);
bh
=
bread
(
s
->
s_dev
,
0
,
SECTOR_SIZE
);
unlock_super
(
s
);
unlock_super
(
s
);
if
(
bh
==
NULL
)
{
if
(
bh
==
NULL
)
{
...
...
fs/msdos/misc.c
View file @
a6614639
...
@@ -256,7 +256,6 @@ int msdos_get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
...
@@ -256,7 +256,6 @@ int msdos_get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
struct
msdos_dir_entry
**
de
)
struct
msdos_dir_entry
**
de
)
{
{
int
sector
,
offset
;
int
sector
,
offset
;
void
*
data
;
while
(
1
)
{
while
(
1
)
{
offset
=
*
pos
;
offset
=
*
pos
;
...
@@ -270,12 +269,12 @@ int msdos_get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
...
@@ -270,12 +269,12 @@ int msdos_get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh,
if
(
*
bh
)
if
(
*
bh
)
brelse
(
*
bh
);
brelse
(
*
bh
);
PRINTK
((
"get_entry sector apres brelse
\n
"
));
PRINTK
((
"get_entry sector apres brelse
\n
"
));
if
(
!
(
*
bh
=
msdos_sread
(
dir
->
i_dev
,
sector
,
&
data
)))
{
if
(
!
(
*
bh
=
msdos_sread
(
dir
->
i_dev
,
sector
)))
{
printk
(
"Directory sread (sector %d) failed
\n
"
,
sector
);
printk
(
"Directory sread (sector %d) failed
\n
"
,
sector
);
continue
;
continue
;
}
}
PRINTK
((
"get_entry apres sread
\n
"
));
PRINTK
((
"get_entry apres sread
\n
"
));
*
de
=
(
struct
msdos_dir_entry
*
)
(
data
+
(
offset
&
*
de
=
(
struct
msdos_dir_entry
*
)
(
(
*
bh
)
->
b_
data
+
(
offset
&
(
SECTOR_SIZE
-
1
)));
(
SECTOR_SIZE
-
1
)));
return
(
sector
<<
MSDOS_DPS_BITS
)
+
((
offset
&
(
SECTOR_SIZE
-
1
))
>>
return
(
sector
<<
MSDOS_DPS_BITS
)
+
((
offset
&
(
SECTOR_SIZE
-
1
))
>>
MSDOS_DIR_BITS
);
MSDOS_DIR_BITS
);
...
@@ -344,7 +343,8 @@ static int raw_scan_sector(struct super_block *sb,int sector,char *name,
...
@@ -344,7 +343,8 @@ static int raw_scan_sector(struct super_block *sb,int sector,char *name,
struct
inode
*
inode
;
struct
inode
*
inode
;
int
entry
,
start
,
done
;
int
entry
,
start
,
done
;
if
(
!
(
bh
=
msdos_sread
(
sb
->
s_dev
,
sector
,(
void
**
)
&
data
)))
return
-
EIO
;
if
(
!
(
bh
=
msdos_sread
(
sb
->
s_dev
,
sector
)))
return
-
EIO
;
data
=
(
struct
msdos_dir_entry
*
)
bh
->
b_data
;
for
(
entry
=
0
;
entry
<
MSDOS_DPS
;
entry
++
)
{
for
(
entry
=
0
;
entry
<
MSDOS_DPS
;
entry
++
)
{
if
(
name
)
RSS_NAME
if
(
name
)
RSS_NAME
else
{
else
{
...
...
fs/read_write.c
View file @
a6614639
...
@@ -33,7 +33,10 @@ asmlinkage int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int
...
@@ -33,7 +33,10 @@ asmlinkage int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int
return
-
EBADF
;
return
-
EBADF
;
error
=
-
ENOTDIR
;
error
=
-
ENOTDIR
;
if
(
file
->
f_op
&&
file
->
f_op
->
readdir
)
{
if
(
file
->
f_op
&&
file
->
f_op
->
readdir
)
{
error
=
verify_area
(
VERIFY_WRITE
,
dirent
,
sizeof
(
*
dirent
));
int
size
=
count
;
if
(
count
==
1
)
size
=
sizeof
(
*
dirent
);
error
=
verify_area
(
VERIFY_WRITE
,
dirent
,
size
);
if
(
!
error
)
if
(
!
error
)
error
=
file
->
f_op
->
readdir
(
inode
,
file
,
dirent
,
count
);
error
=
file
->
f_op
->
readdir
(
inode
,
file
,
dirent
,
count
);
}
}
...
...
fs/umsdos/inode.c
View file @
a6614639
...
@@ -273,7 +273,13 @@ void UMSDOS_write_inode(struct inode *inode)
...
@@ -273,7 +273,13 @@ void UMSDOS_write_inode(struct inode *inode)
newattrs
.
ia_atime
=
inode
->
i_atime
;
newattrs
.
ia_atime
=
inode
->
i_atime
;
newattrs
.
ia_ctime
=
inode
->
i_ctime
;
newattrs
.
ia_ctime
=
inode
->
i_ctime
;
newattrs
.
ia_valid
=
ATTR_MTIME
|
ATTR_ATIME
|
ATTR_CTIME
;
newattrs
.
ia_valid
=
ATTR_MTIME
|
ATTR_ATIME
|
ATTR_CTIME
;
/*
UMSDOS_notify_change is convenient to call here
to update the EMD entry associated with this inode.
But it has the side effect to re"dirt" the inode.
*/
UMSDOS_notify_change
(
inode
,
&
newattrs
);
UMSDOS_notify_change
(
inode
,
&
newattrs
);
inode
->
i_dirt
=
0
;
}
}
int
UMSDOS_notify_change
(
struct
inode
*
inode
,
struct
iattr
*
attr
)
int
UMSDOS_notify_change
(
struct
inode
*
inode
,
struct
iattr
*
attr
)
...
@@ -319,6 +325,7 @@ int UMSDOS_notify_change(struct inode *inode, struct iattr *attr)
...
@@ -319,6 +325,7 @@ int UMSDOS_notify_change(struct inode *inode, struct iattr *attr)
struct
file
filp
;
struct
file
filp
;
struct
umsdos_dirent
entry
;
struct
umsdos_dirent
entry
;
filp
.
f_pos
=
inode
->
u
.
umsdos_i
.
pos
;
filp
.
f_pos
=
inode
->
u
.
umsdos_i
.
pos
;
filp
.
f_reada
=
0
;
PRINTK
((
"pos = %d "
,
filp
.
f_pos
));
PRINTK
((
"pos = %d "
,
filp
.
f_pos
));
/* Read only the start of the entry since we don't touch */
/* Read only the start of the entry since we don't touch */
/* the name */
/* the name */
...
...
fs/xiafs/bitmap.c
View file @
a6614639
...
@@ -35,7 +35,6 @@ static int find_first_zero(struct buffer_head *bh, int start_bit, int end_bit)
...
@@ -35,7 +35,6 @@ static int find_first_zero(struct buffer_head *bh, int start_bit, int end_bit)
int
end
,
i
,
j
,
tmp
;
int
end
,
i
,
j
,
tmp
;
u_long
*
bmap
;
u_long
*
bmap
;
char
res
;
bmap
=
(
u_long
*
)
bh
->
b_data
;
bmap
=
(
u_long
*
)
bh
->
b_data
;
end
=
end_bit
>>
5
;
end
=
end_bit
>>
5
;
...
...
include/linux/cdrom.h
View file @
a6614639
...
@@ -377,10 +377,16 @@ struct cdrom_read_audio
...
@@ -377,10 +377,16 @@ struct cdrom_read_audio
/* read type-1 data */
/* read type-1 data */
/*
/*
* preliminary extension for transferring audio frames
* preliminary extension for transferring audio frames
* currently used by sbpcd.c
* currently used by
cdu31a.c and
sbpcd.c
* (still may change if other drivers will use it, too):
* (still may change if other drivers will use it, too):
*/
*/
#define CDROMREADAUDIO 0x530e
/* (struct cdrom_read_audio) */
#define CDROMREADAUDIO 0x530e
/* (struct cdrom_read_audio) */
/*
* preliminary extension for enable (1) / disable (0) auto-ejecting
* currently used by sbpcd.c
* (still may change if other drivers will use it, too):
*/
#define CDROMEJECT_SW 0x530f
/* arg: 0 or 1 */
#endif _LINUX_CDROM_H
#endif _LINUX_CDROM_H
include/linux/ipc.h
View file @
a6614639
...
@@ -39,7 +39,7 @@ struct ipc_perm
...
@@ -39,7 +39,7 @@ struct ipc_perm
#define IPC_NOID ((void *) -2)
/* being allocated/destroyed */
#define IPC_NOID ((void *) -2)
/* being allocated/destroyed */
/*
/*
* These are used to wrap system calls. See ipc/util.c
, libipc.c
* These are used to wrap system calls. See ipc/util.c
.
*/
*/
struct
ipc_kludge
{
struct
ipc_kludge
{
struct
msgbuf
*
msgp
;
struct
msgbuf
*
msgp
;
...
...
include/linux/msdos_fs.h
View file @
a6614639
...
@@ -110,13 +110,9 @@ struct fat_cache {
...
@@ -110,13 +110,9 @@ struct fat_cache {
#ifdef __KERNEL__
#ifdef __KERNEL__
static
inline
struct
buffer_head
*
msdos_sread
(
int
dev
,
int
sector
,
void
**
start
)
static
inline
struct
buffer_head
*
msdos_sread
(
int
dev
,
int
sector
)
{
{
struct
buffer_head
*
bh
=
bread
(
dev
,
sector
,
512
);
return
bread
(
dev
,
sector
,
SECTOR_SIZE
);
if
(
bh
!=
NULL
){
*
start
=
bh
->
b_data
;
/* From the time of 1024 bytes block */
}
return
bh
;
}
}
...
...
include/linux/msg.h
View file @
a6614639
...
@@ -6,15 +6,6 @@
...
@@ -6,15 +6,6 @@
#define MSG_NOERROR 010000
/* no error if message is too big */
#define MSG_NOERROR 010000
/* no error if message is too big */
#define MSG_EXCEPT 020000
/* recv any msg except of specified type.*/
#define MSG_EXCEPT 020000
/* recv any msg except of specified type.*/
/* one msg structure for each message */
struct
msg
{
struct
msg
*
msg_next
;
/* next message on queue */
long
msg_type
;
char
*
msg_spot
;
/* message text address */
short
msg_ts
;
/* message text size */
};
/* one msqid structure for each queue on the system */
/* one msqid structure for each queue on the system */
struct
msqid_ds
{
struct
msqid_ds
{
struct
ipc_perm
msg_perm
;
struct
ipc_perm
msg_perm
;
...
@@ -32,14 +23,13 @@ struct msqid_ds {
...
@@ -32,14 +23,13 @@ struct msqid_ds {
ushort
msg_lrpid
;
/* last receive pid */
ushort
msg_lrpid
;
/* last receive pid */
};
};
/* message buffer for msgsnd and msgrcv calls */
/* message buffer for msgsnd and msgrcv calls */
struct
msgbuf
{
struct
msgbuf
{
long
mtype
;
/* type of message */
long
mtype
;
/* type of message */
char
mtext
[
1
];
/* message text */
char
mtext
[
1
];
/* message text */
};
};
/* buffer for msgctl calls IPC_INFO, MSG_INFO */
struct
msginfo
{
struct
msginfo
{
int
msgpool
;
int
msgpool
;
int
msgmap
;
int
msgmap
;
...
@@ -65,6 +55,14 @@ struct msginfo {
...
@@ -65,6 +55,14 @@ struct msginfo {
#ifdef __KERNEL__
#ifdef __KERNEL__
/* one msg structure for each message */
struct
msg
{
struct
msg
*
msg_next
;
/* next message on queue */
long
msg_type
;
char
*
msg_spot
;
/* message text address */
short
msg_ts
;
/* message text size */
};
/* ipcs ctl commands */
/* ipcs ctl commands */
#define MSG_STAT 11
#define MSG_STAT 11
#define MSG_INFO 12
#define MSG_INFO 12
...
...
include/linux/sched.h
View file @
a6614639
...
@@ -290,7 +290,7 @@ struct task_struct {
...
@@ -290,7 +290,7 @@ struct task_struct {
struct
tty_struct
*
tty
;
/* NULL if no tty */
struct
tty_struct
*
tty
;
/* NULL if no tty */
/* shm stuff */
/* shm stuff */
struct
shm_desc
*
shm
;
struct
shm_desc
*
shm
;
struct
sem_undo
*
semun
;
struct
sem_undo
*
semun
do
;
/* ldt for this task - used by Wine. If NULL, default_ldt is used */
/* ldt for this task - used by Wine. If NULL, default_ldt is used */
struct
desc_struct
*
ldt
;
struct
desc_struct
*
ldt
;
/* tss for this task */
/* tss for this task */
...
...
include/linux/sem.h
View file @
a6614639
...
@@ -26,16 +26,7 @@ struct semid_ds {
...
@@ -26,16 +26,7 @@ struct semid_ds {
ushort
sem_nsems
;
/* no. of semaphores in array */
ushort
sem_nsems
;
/* no. of semaphores in array */
};
};
/* semop system calls takes an array of these. */
/* One semaphore structure for each semaphore in the system. */
struct
sem
{
short
sempid
;
/* pid of last operation */
ushort
semval
;
/* current value */
ushort
semncnt
;
/* num procs awaiting increase in semval */
ushort
semzcnt
;
/* num procs awaiting semval = 0 */
};
/* semop system calls takes an array of these.*/
struct
sembuf
{
struct
sembuf
{
ushort
sem_num
;
/* semaphore index in array */
ushort
sem_num
;
/* semaphore index in array */
short
sem_op
;
/* semaphore operation */
short
sem_op
;
/* semaphore operation */
...
@@ -44,12 +35,13 @@ struct sembuf {
...
@@ -44,12 +35,13 @@ struct sembuf {
/* arg for semctl system calls. */
/* arg for semctl system calls. */
union
semun
{
union
semun
{
int
val
;
/* value for SETVAL */
int
val
;
/* value for SETVAL */
struct
semid_ds
*
buf
;
/* buffer for IPC_STAT & IPC_SET */
struct
semid_ds
*
buf
;
/* buffer for IPC_STAT & IPC_SET */
ushort
*
array
;
/* array for GETALL & SETALL */
ushort
*
array
;
/* array for GETALL & SETALL */
struct
seminfo
*
__buf
;
/* buffer for IPC_INFO */
void
*
__pad
;
};
};
struct
seminfo
{
struct
seminfo
{
int
semmap
;
int
semmap
;
int
semmni
;
int
semmni
;
...
@@ -77,6 +69,15 @@ struct seminfo {
...
@@ -77,6 +69,15 @@ struct seminfo {
#define SEMUSZ 20
/* sizeof struct sem_undo */
#define SEMUSZ 20
/* sizeof struct sem_undo */
#ifdef __KERNEL__
#ifdef __KERNEL__
/* One semaphore structure for each semaphore in the system. */
struct
sem
{
short
sempid
;
/* pid of last operation */
ushort
semval
;
/* current value */
ushort
semncnt
;
/* num procs awaiting increase in semval */
ushort
semzcnt
;
/* num procs awaiting semval = 0 */
};
/* ipcs ctl cmds */
/* ipcs ctl cmds */
#define SEM_STAT 18
#define SEM_STAT 18
#define SEM_INFO 19
#define SEM_INFO 19
...
...
include/linux/shm.h
View file @
a6614639
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
#include <linux/ipc.h>
#include <linux/ipc.h>
struct
shmid_ds
{
struct
shmid_ds
{
struct
ipc_perm
shm_perm
;
/* operation perms */
struct
ipc_perm
shm_perm
;
/* operation perms */
int
shm_segsz
;
/* size of segment (bytes) */
int
shm_segsz
;
/* size of segment (bytes) */
time_t
shm_atime
;
/* last attach time */
time_t
shm_atime
;
/* last attach time */
time_t
shm_dtime
;
/* last detach time */
time_t
shm_dtime
;
/* last detach time */
...
@@ -12,9 +12,9 @@ struct shmid_ds {
...
@@ -12,9 +12,9 @@ struct shmid_ds {
unsigned
short
shm_lpid
;
/* pid of last operator */
unsigned
short
shm_lpid
;
/* pid of last operator */
short
shm_nattch
;
/* no. of current attaches */
short
shm_nattch
;
/* no. of current attaches */
/* the following are private */
/* the following are private */
unsigned
short
shm_npages
;
/* size of segment (pages) */
unsigned
short
shm_npages
;
/* size of segment (pages) */
unsigned
long
*
shm_pages
;
/* array of ptrs to frames -> SHMMAX */
unsigned
long
*
shm_pages
;
/* array of ptrs to frames -> SHMMAX */
struct
shm_desc
*
attaches
;
/* descriptors for attaches */
struct
shm_desc
*
attaches
;
/* descriptors for attaches */
};
};
/* mode for attach */
/* mode for attach */
...
@@ -34,34 +34,35 @@ struct shminfo {
...
@@ -34,34 +34,35 @@ struct shminfo {
int
shmall
;
int
shmall
;
};
};
/* address range for shared memory attaches if no address passed to shmat() */
#define SHM_RANGE_START 0x40000000
#define SHM_RANGE_START 0x40000000
#define SHM_RANGE_END 0x60000000
#define SHM_RANGE_END 0x60000000
/* _SHM_ID_BITS is a variable you can adjust to */
/* format of page table entries that correspond to shared memory pages
/* tune the kernel. It determines the value of */
currently out in swap space (see also mm/swap.c):
/* SHMMNI, which specifies the maximum no. of */
bit 0 (PAGE_PRESENT) is = 0
/* shared segments (system wide). SRB. */
bits 7..1 (SWP_TYPE) are = SHM_SWP_TYPE
#define _SHM_ID_BITS 7
/* keep as low as possible */
bits 31..8 are used like this:
/* a static array is declared */
bits 14..8 (SHM_ID) the id of the shared memory segment
/* using SHMMNI */
bits 29..15 (SHM_IDX) the index of the page within the shared memory segment
(actually only bits 24..15 get used since SHMMAX is so low)
bit 31 (SHM_READ_ONLY) flag whether the page belongs to a read-only attach
*/
#define __SHM_IDX_BITS (BITS_PER_PTR-2-SHM_IDX_SHIFT)
/* !!!!!!!?????
* Why reserve the two (2) high bits of the signature (shm_sgn) field?
* Since, as far as I can see, only the high bit is used (SHM_READ_ONLY).
* SRB.
*/
#define _SHM_IDX_BITS (__SHM_IDX_BITS+PAGE_SHIFT>=BITS_PER_PTR?\
BITS_PER_PTR-PAGE_SHIFT-1:__SHM_IDX_BITS)
/* sanity check */
/* not present page table entry format bit 0 is 0, low byte defined in mm.h */
#define SHM_ID_SHIFT 8
#define SHM_ID_SHIFT 8
/* Keep _SHM_ID_BITS as low as possible since SHMMNI depends on it and
there is a static array of size SHMMNI. */
#define _SHM_ID_BITS 7
#define SHM_ID_MASK ((1<<_SHM_ID_BITS)-1)
#define SHM_ID_MASK ((1<<_SHM_ID_BITS)-1)
#define SHM_IDX_SHIFT (SHM_ID_SHIFT+_SHM_ID_BITS)
#define SHM_IDX_SHIFT (SHM_ID_SHIFT+_SHM_ID_BITS)
#define _SHM_IDX_BITS 15
#define SHM_IDX_MASK ((1<<_SHM_IDX_BITS)-1)
#define SHM_IDX_MASK ((1<<_SHM_IDX_BITS)-1)
#define SHM_READ_ONLY (1<<(BITS_PER_PTR-1))
#define SHM_READ_ONLY (1<<31)
/* We must have SHM_ID_SHIFT + _SHM_ID_BITS + _SHM_IDX_BITS + 1 <= 32
and SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS). */
#define SHMMAX 0x3fa000
/* max shared seg size (bytes) */
#define SHMMAX 0x3fa000
/* max shared seg size (bytes) */
#define SHMMIN 1
/* really PAGE_SIZE */
/* min shared seg size (bytes) */
#define SHMMIN 1
/* really PAGE_SIZE */
/* min shared seg size (bytes) */
...
@@ -106,4 +107,3 @@ struct shm_desc {
...
@@ -106,4 +107,3 @@ struct shm_desc {
#endif
/* _LINUX_SHM_H_ */
#endif
/* _LINUX_SHM_H_ */
ipc/msg.c
View file @
a6614639
...
@@ -29,7 +29,7 @@ void msg_init (void)
...
@@ -29,7 +29,7 @@ void msg_init (void)
{
{
int
id
;
int
id
;
for
(
id
=
0
;
id
<
MSGMNI
;
id
++
)
for
(
id
=
0
;
id
<
MSGMNI
;
id
++
)
msgque
[
id
]
=
(
struct
msqid_ds
*
)
IPC_UNUSED
;
msgque
[
id
]
=
(
struct
msqid_ds
*
)
IPC_UNUSED
;
msgbytes
=
msghdrs
=
msg_seq
=
max_msqid
=
used_queues
=
0
;
msgbytes
=
msghdrs
=
msg_seq
=
max_msqid
=
used_queues
=
0
;
msg_lock
=
NULL
;
msg_lock
=
NULL
;
...
@@ -53,14 +53,14 @@ int sys_msgsnd (int msqid, struct msgbuf *msgp, int msgsz, int msgflg)
...
@@ -53,14 +53,14 @@ int sys_msgsnd (int msqid, struct msgbuf *msgp, int msgsz, int msgflg)
return
err
;
return
err
;
if
((
mtype
=
get_fs_long
(
&
msgp
->
mtype
))
<
1
)
if
((
mtype
=
get_fs_long
(
&
msgp
->
mtype
))
<
1
)
return
-
EINVAL
;
return
-
EINVAL
;
id
=
msqid
%
MSGMNI
;
id
=
(
unsigned
int
)
msqid
%
MSGMNI
;
msq
=
msgque
[
id
];
msq
=
msgque
[
id
];
if
(
msq
==
IPC_UNUSED
||
msq
==
IPC_NOID
)
if
(
msq
==
IPC_UNUSED
||
msq
==
IPC_NOID
)
return
-
EINVAL
;
return
-
EINVAL
;
ipcp
=
&
msq
->
msg_perm
;
ipcp
=
&
msq
->
msg_perm
;
slept:
slept:
if
(
ipcp
->
seq
!=
(
msqid
/
MSGMNI
)
)
if
(
msq
->
msg_perm
.
seq
!=
(
unsigned
int
)
msqid
/
MSGMNI
)
return
-
EIDRM
;
return
-
EIDRM
;
if
(
ipcperms
(
ipcp
,
S_IWUGO
))
if
(
ipcperms
(
ipcp
,
S_IWUGO
))
return
-
EACCES
;
return
-
EACCES
;
...
@@ -83,7 +83,7 @@ int sys_msgsnd (int msqid, struct msgbuf *msgp, int msgsz, int msgflg)
...
@@ -83,7 +83,7 @@ int sys_msgsnd (int msqid, struct msgbuf *msgp, int msgsz, int msgflg)
memcpy_fromfs
(
msgh
->
msg_spot
,
msgp
->
mtext
,
msgsz
);
memcpy_fromfs
(
msgh
->
msg_spot
,
msgp
->
mtext
,
msgsz
);
if
(
msgque
[
id
]
==
IPC_UNUSED
||
msgque
[
id
]
==
IPC_NOID
if
(
msgque
[
id
]
==
IPC_UNUSED
||
msgque
[
id
]
==
IPC_NOID
||
ipcp
->
seq
!=
msqid
/
MSGMNI
)
{
||
msq
->
msg_perm
.
seq
!=
(
unsigned
int
)
msqid
/
MSGMNI
)
{
kfree
(
msgh
);
kfree
(
msgh
);
return
-
EIDRM
;
return
-
EIDRM
;
}
}
...
@@ -125,7 +125,7 @@ int sys_msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp,
...
@@ -125,7 +125,7 @@ int sys_msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp,
if
(
err
)
if
(
err
)
return
err
;
return
err
;
id
=
msqid
%
MSGMNI
;
id
=
(
unsigned
int
)
msqid
%
MSGMNI
;
msq
=
msgque
[
id
];
msq
=
msgque
[
id
];
if
(
msq
==
IPC_NOID
||
msq
==
IPC_UNUSED
)
if
(
msq
==
IPC_NOID
||
msq
==
IPC_UNUSED
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -138,7 +138,7 @@ int sys_msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp,
...
@@ -138,7 +138,7 @@ int sys_msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp,
* msgtyp < 0 => get message with least type must be < abs(msgtype).
* msgtyp < 0 => get message with least type must be < abs(msgtype).
*/
*/
while
(
!
nmsg
)
{
while
(
!
nmsg
)
{
if
(
ipcp
->
seq
!=
msqid
/
MSGMNI
)
if
(
msq
->
msg_perm
.
seq
!=
(
unsigned
int
)
msqid
/
MSGMNI
)
return
-
EIDRM
;
return
-
EIDRM
;
if
(
ipcperms
(
ipcp
,
S_IRUGO
))
if
(
ipcperms
(
ipcp
,
S_IRUGO
))
return
-
EACCES
;
return
-
EACCES
;
...
@@ -174,7 +174,7 @@ int sys_msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp,
...
@@ -174,7 +174,7 @@ int sys_msgrcv (int msqid, struct msgbuf *msgp, int msgsz, long msgtyp,
if
(
nmsg
==
msq
->
msg_first
)
if
(
nmsg
==
msq
->
msg_first
)
msq
->
msg_first
=
nmsg
->
msg_next
;
msq
->
msg_first
=
nmsg
->
msg_next
;
else
{
else
{
for
(
tmsg
=
msq
->
msg_first
;
tmsg
;
for
(
tmsg
=
msq
->
msg_first
;
tmsg
;
tmsg
=
tmsg
->
msg_next
)
tmsg
=
tmsg
->
msg_next
)
if
(
tmsg
->
msg_next
==
nmsg
)
if
(
tmsg
->
msg_next
==
nmsg
)
break
;
break
;
...
@@ -213,7 +213,7 @@ static int findkey (key_t key)
...
@@ -213,7 +213,7 @@ static int findkey (key_t key)
int
id
;
int
id
;
struct
msqid_ds
*
msq
;
struct
msqid_ds
*
msq
;
for
(
id
=
0
;
id
<=
max_msqid
;
id
++
)
{
for
(
id
=
0
;
id
<=
max_msqid
;
id
++
)
{
while
((
msq
=
msgque
[
id
])
==
IPC_NOID
)
while
((
msq
=
msgque
[
id
])
==
IPC_NOID
)
interruptible_sleep_on
(
&
msg_lock
);
interruptible_sleep_on
(
&
msg_lock
);
if
(
msq
==
IPC_UNUSED
)
if
(
msq
==
IPC_UNUSED
)
...
@@ -230,7 +230,7 @@ static int newque (key_t key, int msgflg)
...
@@ -230,7 +230,7 @@ static int newque (key_t key, int msgflg)
struct
msqid_ds
*
msq
;
struct
msqid_ds
*
msq
;
struct
ipc_perm
*
ipcp
;
struct
ipc_perm
*
ipcp
;
for
(
id
=
0
;
id
<
MSGMNI
;
id
++
)
for
(
id
=
0
;
id
<
MSGMNI
;
id
++
)
if
(
msgque
[
id
]
==
IPC_UNUSED
)
{
if
(
msgque
[
id
]
==
IPC_UNUSED
)
{
msgque
[
id
]
=
(
struct
msqid_ds
*
)
IPC_NOID
;
msgque
[
id
]
=
(
struct
msqid_ds
*
)
IPC_NOID
;
goto
found
;
goto
found
;
...
@@ -250,7 +250,7 @@ static int newque (key_t key, int msgflg)
...
@@ -250,7 +250,7 @@ static int newque (key_t key, int msgflg)
ipcp
->
key
=
key
;
ipcp
->
key
=
key
;
ipcp
->
cuid
=
ipcp
->
uid
=
current
->
euid
;
ipcp
->
cuid
=
ipcp
->
uid
=
current
->
euid
;
ipcp
->
gid
=
ipcp
->
cgid
=
current
->
egid
;
ipcp
->
gid
=
ipcp
->
cgid
=
current
->
egid
;
ipcp
->
seq
=
msg_seq
;
msq
->
msg_perm
.
seq
=
msg_seq
;
msq
->
msg_first
=
msq
->
msg_last
=
NULL
;
msq
->
msg_first
=
msq
->
msg_last
=
NULL
;
msq
->
rwait
=
msq
->
wwait
=
NULL
;
msq
->
rwait
=
msq
->
wwait
=
NULL
;
msq
->
msg_cbytes
=
msq
->
msg_qnum
=
0
;
msq
->
msg_cbytes
=
msq
->
msg_qnum
=
0
;
...
@@ -264,7 +264,7 @@ static int newque (key_t key, int msgflg)
...
@@ -264,7 +264,7 @@ static int newque (key_t key, int msgflg)
used_queues
++
;
used_queues
++
;
if
(
msg_lock
)
if
(
msg_lock
)
wake_up
(
&
msg_lock
);
wake_up
(
&
msg_lock
);
return
(
int
)
msg_
seq
*
MSGMNI
+
id
;
return
(
unsigned
int
)
msq
->
msg_perm
.
seq
*
MSGMNI
+
id
;
}
}
int
sys_msgget
(
key_t
key
,
int
msgflg
)
int
sys_msgget
(
key_t
key
,
int
msgflg
)
...
@@ -286,7 +286,7 @@ int sys_msgget (key_t key, int msgflg)
...
@@ -286,7 +286,7 @@ int sys_msgget (key_t key, int msgflg)
return
-
EIDRM
;
return
-
EIDRM
;
if
(
ipcperms
(
&
msq
->
msg_perm
,
msgflg
))
if
(
ipcperms
(
&
msq
->
msg_perm
,
msgflg
))
return
-
EACCES
;
return
-
EACCES
;
return
msq
->
msg_perm
.
seq
*
MSGMNI
+
id
;
return
(
unsigned
int
)
msq
->
msg_perm
.
seq
*
MSGMNI
+
id
;
}
}
static
void
freeque
(
int
id
)
static
void
freeque
(
int
id
)
...
@@ -295,7 +295,7 @@ static void freeque (int id)
...
@@ -295,7 +295,7 @@ static void freeque (int id)
struct
msg
*
msgp
,
*
msgh
;
struct
msg
*
msgp
,
*
msgh
;
msq
->
msg_perm
.
seq
++
;
msq
->
msg_perm
.
seq
++
;
msg_seq
++
;
msg_seq
=
(
msg_seq
+
1
)
%
((
unsigned
)(
1
<<
31
)
/
MSGMNI
);
/* increment, but avoid overflow */
msgbytes
-=
msq
->
msg_cbytes
;
msgbytes
-=
msq
->
msg_cbytes
;
if
(
id
==
max_msqid
)
if
(
id
==
max_msqid
)
while
(
max_msqid
&&
(
msgque
[
--
max_msqid
]
==
IPC_UNUSED
));
while
(
max_msqid
&&
(
msgque
[
--
max_msqid
]
==
IPC_UNUSED
));
...
@@ -319,7 +319,8 @@ static void freeque (int id)
...
@@ -319,7 +319,8 @@ static void freeque (int id)
int
sys_msgctl
(
int
msqid
,
int
cmd
,
struct
msqid_ds
*
buf
)
int
sys_msgctl
(
int
msqid
,
int
cmd
,
struct
msqid_ds
*
buf
)
{
{
int
id
,
err
;
int
id
,
err
;
struct
msqid_ds
*
msq
,
tbuf
;
struct
msqid_ds
*
msq
;
struct
msqid_ds
tbuf
;
struct
ipc_perm
*
ipcp
;
struct
ipc_perm
*
ipcp
;
if
(
msqid
<
0
||
cmd
<
0
)
if
(
msqid
<
0
||
cmd
<
0
)
...
@@ -353,7 +354,7 @@ int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
...
@@ -353,7 +354,7 @@ int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
case
MSG_STAT
:
case
MSG_STAT
:
if
(
!
buf
)
if
(
!
buf
)
return
-
EFAULT
;
return
-
EFAULT
;
err
=
verify_area
(
VERIFY_WRITE
,
buf
,
sizeof
(
*
msq
));
err
=
verify_area
(
VERIFY_WRITE
,
buf
,
sizeof
(
*
buf
));
if
(
err
)
if
(
err
)
return
err
;
return
err
;
if
(
msqid
>
max_msqid
)
if
(
msqid
>
max_msqid
)
...
@@ -363,46 +364,62 @@ int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
...
@@ -363,46 +364,62 @@ int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
ipcperms
(
&
msq
->
msg_perm
,
S_IRUGO
))
if
(
ipcperms
(
&
msq
->
msg_perm
,
S_IRUGO
))
return
-
EACCES
;
return
-
EACCES
;
id
=
msqid
+
msq
->
msg_perm
.
seq
*
MSGMNI
;
id
=
(
unsigned
int
)
msq
->
msg_perm
.
seq
*
MSGMNI
+
msqid
;
memcpy_tofs
(
buf
,
msq
,
sizeof
(
*
msq
));
tbuf
.
msg_perm
=
msq
->
msg_perm
;
tbuf
.
msg_stime
=
msq
->
msg_stime
;
tbuf
.
msg_rtime
=
msq
->
msg_rtime
;
tbuf
.
msg_ctime
=
msq
->
msg_ctime
;
tbuf
.
msg_cbytes
=
msq
->
msg_cbytes
;
tbuf
.
msg_qnum
=
msq
->
msg_qnum
;
tbuf
.
msg_qbytes
=
msq
->
msg_qbytes
;
tbuf
.
msg_lspid
=
msq
->
msg_lspid
;
tbuf
.
msg_lrpid
=
msq
->
msg_lrpid
;
memcpy_tofs
(
buf
,
&
tbuf
,
sizeof
(
*
buf
));
return
id
;
return
id
;
case
IPC_SET
:
case
IPC_SET
:
if
(
!
buf
)
if
(
!
buf
)
return
-
EFAULT
;
return
-
EFAULT
;
err
=
verify_area
(
VERIFY_READ
,
buf
,
sizeof
(
*
buf
));
if
(
err
)
return
err
;
memcpy_fromfs
(
&
tbuf
,
buf
,
sizeof
(
*
buf
));
memcpy_fromfs
(
&
tbuf
,
buf
,
sizeof
(
*
buf
));
break
;
break
;
case
IPC_STAT
:
case
IPC_STAT
:
if
(
!
buf
)
if
(
!
buf
)
return
-
EFAULT
;
return
-
EFAULT
;
err
=
verify_area
(
VERIFY_WRITE
,
buf
,
sizeof
(
*
msq
));
err
=
verify_area
(
VERIFY_WRITE
,
buf
,
sizeof
(
*
buf
));
if
(
err
)
if
(
err
)
return
err
;
return
err
;
break
;
break
;
}
}
id
=
msqid
%
MSGMNI
;
id
=
(
unsigned
int
)
msqid
%
MSGMNI
;
msq
=
msgque
[
id
];
msq
=
msgque
[
id
];
if
(
msq
==
IPC_UNUSED
||
msq
==
IPC_NOID
)
if
(
msq
==
IPC_UNUSED
||
msq
==
IPC_NOID
)
return
-
EINVAL
;
return
-
EINVAL
;
ipcp
=
&
msq
->
msg_perm
;
if
(
msq
->
msg_perm
.
seq
!=
(
unsigned
int
)
msqid
/
MSGMNI
)
if
(
ipcp
->
seq
!=
msqid
/
MSGMNI
)
return
-
EIDRM
;
return
-
EIDRM
;
ipcp
=
&
msq
->
msg_perm
;
switch
(
cmd
)
{
switch
(
cmd
)
{
case
IPC_STAT
:
case
IPC_STAT
:
if
(
ipcperms
(
ipcp
,
S_IRUGO
))
if
(
ipcperms
(
ipcp
,
S_IRUGO
))
return
-
EACCES
;
return
-
EACCES
;
memcpy_tofs
(
buf
,
msq
,
sizeof
(
*
msq
));
tbuf
.
msg_perm
=
msq
->
msg_perm
;
tbuf
.
msg_stime
=
msq
->
msg_stime
;
tbuf
.
msg_rtime
=
msq
->
msg_rtime
;
tbuf
.
msg_ctime
=
msq
->
msg_ctime
;
tbuf
.
msg_cbytes
=
msq
->
msg_cbytes
;
tbuf
.
msg_qnum
=
msq
->
msg_qnum
;
tbuf
.
msg_qbytes
=
msq
->
msg_qbytes
;
tbuf
.
msg_lspid
=
msq
->
msg_lspid
;
tbuf
.
msg_lrpid
=
msq
->
msg_lrpid
;
memcpy_tofs
(
buf
,
&
tbuf
,
sizeof
(
*
buf
));
return
0
;
return
0
;
break
;
case
IPC_SET
:
case
IPC_RMID
:
case
IPC_SET
:
if
(
!
suser
()
&&
current
->
euid
!=
ipcp
->
cuid
&&
if
(
!
suser
()
&&
current
->
euid
!=
ipcp
->
cuid
&&
current
->
euid
!=
ipcp
->
uid
)
current
->
euid
!=
ipcp
->
uid
)
return
-
EPERM
;
return
-
EPERM
;
if
(
cmd
==
IPC_RMID
)
{
freeque
(
id
);
return
0
;
}
if
(
tbuf
.
msg_qbytes
>
MSGMNB
&&
!
suser
())
if
(
tbuf
.
msg_qbytes
>
MSGMNB
&&
!
suser
())
return
-
EPERM
;
return
-
EPERM
;
msq
->
msg_qbytes
=
tbuf
.
msg_qbytes
;
msq
->
msg_qbytes
=
tbuf
.
msg_qbytes
;
...
@@ -411,10 +428,14 @@ int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
...
@@ -411,10 +428,14 @@ int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
ipcp
->
mode
=
(
ipcp
->
mode
&
~
S_IRWXUGO
)
|
ipcp
->
mode
=
(
ipcp
->
mode
&
~
S_IRWXUGO
)
|
(
S_IRWXUGO
&
tbuf
.
msg_perm
.
mode
);
(
S_IRWXUGO
&
tbuf
.
msg_perm
.
mode
);
msq
->
msg_ctime
=
CURRENT_TIME
;
msq
->
msg_ctime
=
CURRENT_TIME
;
break
;
return
0
;
case
IPC_RMID
:
if
(
!
suser
()
&&
current
->
euid
!=
ipcp
->
cuid
&&
current
->
euid
!=
ipcp
->
uid
)
return
-
EPERM
;
freeque
(
id
);
return
0
;
default:
default:
return
-
EINVAL
;
return
-
EINVAL
;
break
;
}
}
return
0
;
}
}
ipc/sem.c
View file @
a6614639
...
@@ -26,11 +26,11 @@ static unsigned short sem_seq = 0;
...
@@ -26,11 +26,11 @@ static unsigned short sem_seq = 0;
void
sem_init
(
void
)
void
sem_init
(
void
)
{
{
int
i
=
0
;
int
i
;
sem_lock
=
NULL
;
sem_lock
=
NULL
;
used_sems
=
used_semids
=
max_semid
=
sem_seq
=
0
;
used_sems
=
used_semids
=
max_semid
=
sem_seq
=
0
;
for
(
i
=
0
;
i
<
SEMMNI
;
i
++
)
for
(
i
=
0
;
i
<
SEMMNI
;
i
++
)
semary
[
i
]
=
(
struct
semid_ds
*
)
IPC_UNUSED
;
semary
[
i
]
=
(
struct
semid_ds
*
)
IPC_UNUSED
;
return
;
return
;
}
}
...
@@ -40,7 +40,7 @@ static int findkey (key_t key)
...
@@ -40,7 +40,7 @@ static int findkey (key_t key)
int
id
;
int
id
;
struct
semid_ds
*
sma
;
struct
semid_ds
*
sma
;
for
(
id
=
0
;
id
<=
max_semid
;
id
++
)
{
for
(
id
=
0
;
id
<=
max_semid
;
id
++
)
{
while
((
sma
=
semary
[
id
])
==
IPC_NOID
)
while
((
sma
=
semary
[
id
])
==
IPC_NOID
)
interruptible_sleep_on
(
&
sem_lock
);
interruptible_sleep_on
(
&
sem_lock
);
if
(
sma
==
IPC_UNUSED
)
if
(
sma
==
IPC_UNUSED
)
...
@@ -62,7 +62,7 @@ static int newary (key_t key, int nsems, int semflg)
...
@@ -62,7 +62,7 @@ static int newary (key_t key, int nsems, int semflg)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
used_sems
+
nsems
>
SEMMNS
)
if
(
used_sems
+
nsems
>
SEMMNS
)
return
-
ENOSPC
;
return
-
ENOSPC
;
for
(
id
=
0
;
id
<
SEMMNI
;
id
++
)
for
(
id
=
0
;
id
<
SEMMNI
;
id
++
)
if
(
semary
[
id
]
==
IPC_UNUSED
)
{
if
(
semary
[
id
]
==
IPC_UNUSED
)
{
semary
[
id
]
=
(
struct
semid_ds
*
)
IPC_NOID
;
semary
[
id
]
=
(
struct
semid_ds
*
)
IPC_NOID
;
goto
found
;
goto
found
;
...
@@ -86,7 +86,7 @@ static int newary (key_t key, int nsems, int semflg)
...
@@ -86,7 +86,7 @@ static int newary (key_t key, int nsems, int semflg)
ipcp
->
key
=
key
;
ipcp
->
key
=
key
;
ipcp
->
cuid
=
ipcp
->
uid
=
current
->
euid
;
ipcp
->
cuid
=
ipcp
->
uid
=
current
->
euid
;
ipcp
->
gid
=
ipcp
->
cgid
=
current
->
egid
;
ipcp
->
gid
=
ipcp
->
cgid
=
current
->
egid
;
ipcp
->
seq
=
sem_seq
;
sma
->
sem_perm
.
seq
=
sem_seq
;
sma
->
eventn
=
sma
->
eventz
=
NULL
;
sma
->
eventn
=
sma
->
eventz
=
NULL
;
sma
->
sem_nsems
=
nsems
;
sma
->
sem_nsems
=
nsems
;
sma
->
sem_ctime
=
CURRENT_TIME
;
sma
->
sem_ctime
=
CURRENT_TIME
;
...
@@ -96,7 +96,7 @@ static int newary (key_t key, int nsems, int semflg)
...
@@ -96,7 +96,7 @@ static int newary (key_t key, int nsems, int semflg)
semary
[
id
]
=
sma
;
semary
[
id
]
=
sma
;
if
(
sem_lock
)
if
(
sem_lock
)
wake_up
(
&
sem_lock
);
wake_up
(
&
sem_lock
);
return
(
int
)
sem_
seq
*
SEMMNI
+
id
;
return
(
unsigned
int
)
sma
->
sem_perm
.
seq
*
SEMMNI
+
id
;
}
}
int
sys_semget
(
key_t
key
,
int
nsems
,
int
semflg
)
int
sys_semget
(
key_t
key
,
int
nsems
,
int
semflg
)
...
@@ -120,7 +120,7 @@ int sys_semget (key_t key, int nsems, int semflg)
...
@@ -120,7 +120,7 @@ int sys_semget (key_t key, int nsems, int semflg)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
ipcperms
(
&
sma
->
sem_perm
,
semflg
))
if
(
ipcperms
(
&
sma
->
sem_perm
,
semflg
))
return
-
EACCES
;
return
-
EACCES
;
return
sma
->
sem_perm
.
seq
*
SEMMNI
+
id
;
return
(
unsigned
int
)
sma
->
sem_perm
.
seq
*
SEMMNI
+
id
;
}
}
static
void
freeary
(
int
id
)
static
void
freeary
(
int
id
)
...
@@ -129,13 +129,13 @@ static void freeary (int id)
...
@@ -129,13 +129,13 @@ static void freeary (int id)
struct
sem_undo
*
un
;
struct
sem_undo
*
un
;
sma
->
sem_perm
.
seq
++
;
sma
->
sem_perm
.
seq
++
;
sem_seq
++
;
sem_seq
=
(
sem_seq
+
1
)
%
((
unsigned
)(
1
<<
31
)
/
SEMMNI
);
/* increment, but avoid overflow */
used_sems
-=
sma
->
sem_nsems
;
used_sems
-=
sma
->
sem_nsems
;
if
(
id
==
max_semid
)
if
(
id
==
max_semid
)
while
(
max_semid
&&
(
semary
[
--
max_semid
]
==
IPC_UNUSED
));
while
(
max_semid
&&
(
semary
[
--
max_semid
]
==
IPC_UNUSED
));
semary
[
id
]
=
(
struct
semid_ds
*
)
IPC_UNUSED
;
semary
[
id
]
=
(
struct
semid_ds
*
)
IPC_UNUSED
;
used_semids
--
;
used_semids
--
;
for
(
un
=
sma
->
undo
;
un
;
un
=
un
->
id_next
)
for
(
un
=
sma
->
undo
;
un
;
un
=
un
->
id_next
)
un
->
semadj
=
0
;
un
->
semadj
=
0
;
while
(
sma
->
eventz
||
sma
->
eventn
)
{
while
(
sma
->
eventz
||
sma
->
eventn
)
{
if
(
sma
->
eventz
)
if
(
sma
->
eventz
)
...
@@ -148,16 +148,19 @@ static void freeary (int id)
...
@@ -148,16 +148,19 @@ static void freeary (int id)
return
;
return
;
}
}
int
sys_semctl
(
int
semid
,
int
semnum
,
int
cmd
,
void
*
arg
)
int
sys_semctl
(
int
semid
,
int
semnum
,
int
cmd
,
union
semun
arg
)
{
{
struct
semid_ds
*
buf
=
NULL
;
struct
semid_ds
tbuf
;
int
i
,
id
,
val
=
0
;
int
i
,
id
,
val
=
0
;
struct
semid_ds
*
sma
,
*
buf
=
NULL
,
tbuf
;
struct
semid_ds
*
sma
;
struct
ipc_perm
*
ipcp
;
struct
ipc_perm
*
ipcp
;
struct
sem
*
curr
;
struct
sem
*
curr
;
struct
sem_undo
*
un
;
struct
sem_undo
*
un
;
ushort
nsems
,
*
array
=
NULL
;
unsigned
int
nsems
;
ushort
*
array
=
NULL
;
ushort
sem_io
[
SEMMSL
];
ushort
sem_io
[
SEMMSL
];
if
(
semid
<
0
||
semnum
<
0
||
cmd
<
0
)
if
(
semid
<
0
||
semnum
<
0
||
cmd
<
0
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -165,9 +168,7 @@ int sys_semctl (int semid, int semnum, int cmd, void *arg)
...
@@ -165,9 +168,7 @@ int sys_semctl (int semid, int semnum, int cmd, void *arg)
case
IPC_INFO
:
case
IPC_INFO
:
case
SEM_INFO
:
case
SEM_INFO
:
{
{
struct
seminfo
seminfo
,
*
tmp
;
struct
seminfo
seminfo
,
*
tmp
=
arg
.
__buf
;
if
(
!
arg
||
!
(
tmp
=
(
struct
seminfo
*
)
get_fs_long
((
int
*
)
arg
)))
return
-
EFAULT
;
seminfo
.
semmni
=
SEMMNI
;
seminfo
.
semmni
=
SEMMNI
;
seminfo
.
semmns
=
SEMMNS
;
seminfo
.
semmns
=
SEMMNS
;
seminfo
.
semmsl
=
SEMMSL
;
seminfo
.
semmsl
=
SEMMSL
;
...
@@ -182,7 +183,7 @@ int sys_semctl (int semid, int semnum, int cmd, void *arg)
...
@@ -182,7 +183,7 @@ int sys_semctl (int semid, int semnum, int cmd, void *arg)
seminfo
.
semusz
=
used_semids
;
seminfo
.
semusz
=
used_semids
;
seminfo
.
semaem
=
used_sems
;
seminfo
.
semaem
=
used_sems
;
}
}
i
=
verify_area
(
VERIFY_WRITE
,
tmp
,
sizeof
(
struct
seminfo
));
i
=
verify_area
(
VERIFY_WRITE
,
tmp
,
sizeof
(
struct
seminfo
));
if
(
i
)
if
(
i
)
return
i
;
return
i
;
memcpy_tofs
(
tmp
,
&
seminfo
,
sizeof
(
struct
seminfo
));
memcpy_tofs
(
tmp
,
&
seminfo
,
sizeof
(
struct
seminfo
));
...
@@ -190,9 +191,8 @@ int sys_semctl (int semid, int semnum, int cmd, void *arg)
...
@@ -190,9 +191,8 @@ int sys_semctl (int semid, int semnum, int cmd, void *arg)
}
}
case
SEM_STAT
:
case
SEM_STAT
:
if
(
!
arg
||
!
(
buf
=
(
struct
semid_ds
*
)
get_fs_long
((
int
*
)
arg
)))
buf
=
arg
.
buf
;
return
-
EFAULT
;
i
=
verify_area
(
VERIFY_WRITE
,
buf
,
sizeof
(
*
buf
));
i
=
verify_area
(
VERIFY_WRITE
,
buf
,
sizeof
(
*
sma
));
if
(
i
)
if
(
i
)
return
i
;
return
i
;
if
(
semid
>
max_semid
)
if
(
semid
>
max_semid
)
...
@@ -202,18 +202,22 @@ int sys_semctl (int semid, int semnum, int cmd, void *arg)
...
@@ -202,18 +202,22 @@ int sys_semctl (int semid, int semnum, int cmd, void *arg)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
ipcperms
(
&
sma
->
sem_perm
,
S_IRUGO
))
if
(
ipcperms
(
&
sma
->
sem_perm
,
S_IRUGO
))
return
-
EACCES
;
return
-
EACCES
;
id
=
semid
+
sma
->
sem_perm
.
seq
*
SEMMNI
;
id
=
(
unsigned
int
)
sma
->
sem_perm
.
seq
*
SEMMNI
+
semid
;
memcpy_tofs
(
buf
,
sma
,
sizeof
(
*
sma
));
tbuf
.
sem_perm
=
sma
->
sem_perm
;
tbuf
.
sem_otime
=
sma
->
sem_otime
;
tbuf
.
sem_ctime
=
sma
->
sem_ctime
;
tbuf
.
sem_nsems
=
sma
->
sem_nsems
;
memcpy_tofs
(
buf
,
&
tbuf
,
sizeof
(
*
buf
));
return
id
;
return
id
;
}
}
id
=
semid
%
SEMMNI
;
id
=
(
unsigned
int
)
semid
%
SEMMNI
;
sma
=
semary
[
id
];
sma
=
semary
[
id
];
if
(
sma
==
IPC_UNUSED
||
sma
==
IPC_NOID
)
if
(
sma
==
IPC_UNUSED
||
sma
==
IPC_NOID
)
return
-
EINVAL
;
return
-
EINVAL
;
ipcp
=
&
sma
->
sem_perm
;
ipcp
=
&
sma
->
sem_perm
;
nsems
=
sma
->
sem_nsems
;
nsems
=
sma
->
sem_nsems
;
if
(
ipcp
->
seq
!=
semid
/
SEMMNI
)
if
(
sma
->
sem_perm
.
seq
!=
(
unsigned
int
)
semid
/
SEMMNI
)
return
-
EIDRM
;
return
-
EIDRM
;
if
(
semnum
>=
nsems
)
if
(
semnum
>=
nsems
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -233,17 +237,15 @@ int sys_semctl (int semid, int semnum, int cmd, void *arg)
...
@@ -233,17 +237,15 @@ int sys_semctl (int semid, int semnum, int cmd, void *arg)
case
GETNCNT
:
return
curr
->
semncnt
;
case
GETNCNT
:
return
curr
->
semncnt
;
case
GETZCNT
:
return
curr
->
semzcnt
;
case
GETZCNT
:
return
curr
->
semzcnt
;
case
GETALL
:
case
GETALL
:
if
(
!
arg
||
!
(
array
=
(
ushort
*
)
get_fs_long
((
int
*
)
arg
)))
array
=
arg
.
array
;
return
-
EFAULT
;
i
=
verify_area
(
VERIFY_WRITE
,
array
,
nsems
*
sizeof
(
ushort
));
i
=
verify_area
(
VERIFY_WRITE
,
array
,
nsems
*
sizeof
(
short
));
if
(
i
)
if
(
i
)
return
i
;
return
i
;
}
}
break
;
break
;
case
SETVAL
:
case
SETVAL
:
if
(
!
arg
)
val
=
arg
.
val
;
return
-
EFAULT
;
if
(
val
>
SEMVMX
||
val
<
0
)
if
((
val
=
(
int
)
get_fs_long
((
int
*
)
arg
))
>
SEMVMX
||
val
<
0
)
return
-
ERANGE
;
return
-
ERANGE
;
break
;
break
;
case
IPC_RMID
:
case
IPC_RMID
:
...
@@ -254,40 +256,37 @@ int sys_semctl (int semid, int semnum, int cmd, void *arg)
...
@@ -254,40 +256,37 @@ int sys_semctl (int semid, int semnum, int cmd, void *arg)
}
}
return
-
EPERM
;
return
-
EPERM
;
case
SETALL
:
/* arg is a pointer to an array of ushort */
case
SETALL
:
/* arg is a pointer to an array of ushort */
if
(
!
arg
||
!
(
array
=
(
ushort
*
)
get_fs_long
((
int
*
)
arg
))
)
array
=
arg
.
array
;
return
-
EFAULT
;
if
((
i
=
verify_area
(
VERIFY_READ
,
array
,
nsems
*
sizeof
(
ushort
))))
if
((
i
=
verify_area
(
VERIFY_READ
,
array
,
sizeof
tbuf
)))
return
i
;
return
i
;
memcpy_fromfs
(
sem_io
,
array
,
nsems
*
sizeof
(
ushort
));
memcpy_fromfs
(
sem_io
,
array
,
nsems
*
sizeof
(
ushort
));
for
(
i
=
0
;
i
<
nsems
;
i
++
)
for
(
i
=
0
;
i
<
nsems
;
i
++
)
if
(
sem_io
[
i
]
>
SEMVMX
)
if
(
sem_io
[
i
]
>
SEMVMX
)
return
-
ERANGE
;
return
-
ERANGE
;
break
;
break
;
case
IPC_STAT
:
case
IPC_STAT
:
if
(
!
arg
||
!
(
buf
=
(
struct
semid_ds
*
)
get_fs_long
((
int
*
)
arg
)))
buf
=
arg
.
buf
;
return
-
EFAULT
;
if
((
i
=
verify_area
(
VERIFY_WRITE
,
buf
,
sizeof
(
*
buf
))))
if
((
i
=
verify_area
(
VERIFY_WRITE
,
buf
,
sizeof
(
*
sma
))))
return
i
;
return
i
;
break
;
break
;
case
IPC_SET
:
case
IPC_SET
:
if
(
!
arg
||
!
(
buf
=
(
struct
semid_ds
*
)
get_fs_long
((
int
*
)
arg
)))
buf
=
arg
.
buf
;
return
-
EFAULT
;
if
((
i
=
verify_area
(
VERIFY_READ
,
buf
,
sizeof
(
*
buf
))))
if
((
i
=
verify_area
(
VERIFY_READ
,
buf
,
sizeof
tbuf
)))
return
i
;
return
i
;
memcpy_fromfs
(
&
tbuf
,
buf
,
sizeof
tbuf
);
memcpy_fromfs
(
&
tbuf
,
buf
,
sizeof
(
*
buf
)
);
break
;
break
;
}
}
if
(
semary
[
id
]
==
IPC_UNUSED
||
semary
[
id
]
==
IPC_NOID
)
if
(
semary
[
id
]
==
IPC_UNUSED
||
semary
[
id
]
==
IPC_NOID
)
return
-
EIDRM
;
return
-
EIDRM
;
if
(
ipcp
->
seq
!=
semid
/
SEMMNI
)
if
(
sma
->
sem_perm
.
seq
!=
(
unsigned
int
)
semid
/
SEMMNI
)
return
-
EIDRM
;
return
-
EIDRM
;
switch
(
cmd
)
{
switch
(
cmd
)
{
case
GETALL
:
case
GETALL
:
if
(
ipcperms
(
ipcp
,
S_IRUGO
))
if
(
ipcperms
(
ipcp
,
S_IRUGO
))
return
-
EACCES
;
return
-
EACCES
;
for
(
i
=
0
;
i
<
sma
->
sem_nsems
;
i
++
)
for
(
i
=
0
;
i
<
sma
->
sem_nsems
;
i
++
)
sem_io
[
i
]
=
sma
->
sem_base
[
i
].
semval
;
sem_io
[
i
]
=
sma
->
sem_base
[
i
].
semval
;
memcpy_tofs
(
array
,
sem_io
,
nsems
*
sizeof
(
ushort
));
memcpy_tofs
(
array
,
sem_io
,
nsems
*
sizeof
(
ushort
));
break
;
break
;
...
@@ -318,12 +317,16 @@ int sys_semctl (int semid, int semnum, int cmd, void *arg)
...
@@ -318,12 +317,16 @@ int sys_semctl (int semid, int semnum, int cmd, void *arg)
case
IPC_STAT
:
case
IPC_STAT
:
if
(
ipcperms
(
ipcp
,
S_IRUGO
))
if
(
ipcperms
(
ipcp
,
S_IRUGO
))
return
-
EACCES
;
return
-
EACCES
;
memcpy_tofs
(
buf
,
sma
,
sizeof
(
*
sma
));
tbuf
.
sem_perm
=
sma
->
sem_perm
;
tbuf
.
sem_otime
=
sma
->
sem_otime
;
tbuf
.
sem_ctime
=
sma
->
sem_ctime
;
tbuf
.
sem_nsems
=
sma
->
sem_nsems
;
memcpy_tofs
(
buf
,
&
tbuf
,
sizeof
(
*
buf
));
break
;
break
;
case
SETALL
:
case
SETALL
:
if
(
ipcperms
(
ipcp
,
S_IWUGO
))
if
(
ipcperms
(
ipcp
,
S_IWUGO
))
return
-
EACCES
;
return
-
EACCES
;
for
(
i
=
0
;
i
<
nsems
;
i
++
)
for
(
i
=
0
;
i
<
nsems
;
i
++
)
sma
->
sem_base
[
i
].
semval
=
sem_io
[
i
];
sma
->
sem_base
[
i
].
semval
=
sem_io
[
i
];
for
(
un
=
sma
->
undo
;
un
;
un
=
un
->
id_next
)
for
(
un
=
sma
->
undo
;
un
;
un
=
un
->
id_next
)
un
->
semadj
=
0
;
un
->
semadj
=
0
;
...
@@ -354,11 +357,13 @@ int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
...
@@ -354,11 +357,13 @@ int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
return
-
E2BIG
;
return
-
E2BIG
;
if
(
!
tsops
)
if
(
!
tsops
)
return
-
EFAULT
;
return
-
EFAULT
;
if
((
i
=
verify_area
(
VERIFY_READ
,
tsops
,
nsops
*
sizeof
(
*
tsops
))))
return
i
;
memcpy_fromfs
(
sops
,
tsops
,
nsops
*
sizeof
(
*
tsops
));
memcpy_fromfs
(
sops
,
tsops
,
nsops
*
sizeof
(
*
tsops
));
id
=
semid
%
SEMMNI
;
id
=
(
unsigned
int
)
semid
%
SEMMNI
;
if
((
sma
=
semary
[
id
])
==
IPC_UNUSED
||
sma
==
IPC_NOID
)
if
((
sma
=
semary
[
id
])
==
IPC_UNUSED
||
sma
==
IPC_NOID
)
return
-
EINVAL
;
return
-
EINVAL
;
for
(
i
=
0
;
i
<
nsops
;
i
++
)
{
for
(
i
=
0
;
i
<
nsops
;
i
++
)
{
sop
=
&
sops
[
i
];
sop
=
&
sops
[
i
];
if
(
sop
->
sem_num
>
sma
->
sem_nsems
)
if
(
sop
->
sem_num
>
sma
->
sem_nsems
)
return
-
EFBIG
;
return
-
EFBIG
;
...
@@ -376,10 +381,10 @@ int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
...
@@ -376,10 +381,10 @@ int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
* ensure every sop with undo gets an undo structure
* ensure every sop with undo gets an undo structure
*/
*/
if
(
undos
)
{
if
(
undos
)
{
for
(
i
=
0
;
i
<
nsops
;
i
++
)
{
for
(
i
=
0
;
i
<
nsops
;
i
++
)
{
if
(
!
(
sops
[
i
].
sem_flg
&
SEM_UNDO
))
if
(
!
(
sops
[
i
].
sem_flg
&
SEM_UNDO
))
continue
;
continue
;
for
(
un
=
current
->
semun
;
un
;
un
=
un
->
proc_next
)
for
(
un
=
current
->
semun
do
;
un
;
un
=
un
->
proc_next
)
if
((
un
->
semid
==
semid
)
&&
if
((
un
->
semid
==
semid
)
&&
(
un
->
sem_num
==
sops
[
i
].
sem_num
))
(
un
->
sem_num
==
sops
[
i
].
sem_num
))
break
;
break
;
...
@@ -392,17 +397,17 @@ int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
...
@@ -392,17 +397,17 @@ int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
un
->
semid
=
semid
;
un
->
semid
=
semid
;
un
->
semadj
=
0
;
un
->
semadj
=
0
;
un
->
sem_num
=
sops
[
i
].
sem_num
;
un
->
sem_num
=
sops
[
i
].
sem_num
;
un
->
proc_next
=
current
->
semun
;
un
->
proc_next
=
current
->
semun
do
;
current
->
semun
=
un
;
current
->
semun
do
=
un
;
un
->
id_next
=
sma
->
undo
;
un
->
id_next
=
sma
->
undo
;
sma
->
undo
=
un
;
sma
->
undo
=
un
;
}
}
}
}
slept:
slept:
if
(
sma
->
sem_perm
.
seq
!=
semid
/
SEMMNI
)
if
(
sma
->
sem_perm
.
seq
!=
(
unsigned
int
)
semid
/
SEMMNI
)
return
-
EIDRM
;
return
-
EIDRM
;
for
(
i
=
0
;
i
<
nsops
;
i
++
)
{
for
(
i
=
0
;
i
<
nsops
;
i
++
)
{
sop
=
&
sops
[
i
];
sop
=
&
sops
[
i
];
curr
=
&
sma
->
sem_base
[
sop
->
sem_num
];
curr
=
&
sma
->
sem_base
[
sop
->
sem_num
];
if
(
sop
->
sem_op
+
curr
->
semval
>
SEMVMX
)
if
(
sop
->
sem_op
+
curr
->
semval
>
SEMVMX
)
...
@@ -429,7 +434,7 @@ int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
...
@@ -429,7 +434,7 @@ int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
}
}
}
}
for
(
i
=
0
;
i
<
nsops
;
i
++
)
{
for
(
i
=
0
;
i
<
nsops
;
i
++
)
{
sop
=
&
sops
[
i
];
sop
=
&
sops
[
i
];
curr
=
&
sma
->
sem_base
[
sop
->
sem_num
];
curr
=
&
sma
->
sem_base
[
sop
->
sem_num
];
curr
->
sempid
=
current
->
pid
;
curr
->
sempid
=
current
->
pid
;
...
@@ -437,7 +442,7 @@ int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
...
@@ -437,7 +442,7 @@ int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
semzcnt
++
;
semzcnt
++
;
if
(
!
(
sop
->
sem_flg
&
SEM_UNDO
))
if
(
!
(
sop
->
sem_flg
&
SEM_UNDO
))
continue
;
continue
;
for
(
un
=
current
->
semun
;
un
;
un
=
un
->
proc_next
)
for
(
un
=
current
->
semun
do
;
un
;
un
=
un
->
proc_next
)
if
((
un
->
semid
==
semid
)
&&
if
((
un
->
semid
==
semid
)
&&
(
un
->
sem_num
==
sop
->
sem_num
))
(
un
->
sem_num
==
sop
->
sem_num
))
break
;
break
;
...
@@ -466,11 +471,11 @@ void sem_exit (void)
...
@@ -466,11 +471,11 @@ void sem_exit (void)
struct
semid_ds
*
sma
;
struct
semid_ds
*
sma
;
struct
sem
*
sem
=
NULL
;
struct
sem
*
sem
=
NULL
;
for
(
up
=
&
current
->
semun
;
(
u
=
*
up
);
*
up
=
u
->
proc_next
,
kfree
(
u
))
{
for
(
up
=
&
current
->
semun
do
;
(
u
=
*
up
);
*
up
=
u
->
proc_next
,
kfree
(
u
))
{
sma
=
semary
[
u
->
semid
%
SEMMNI
];
sma
=
semary
[
(
unsigned
int
)
u
->
semid
%
SEMMNI
];
if
(
sma
==
IPC_UNUSED
||
sma
==
IPC_NOID
)
if
(
sma
==
IPC_UNUSED
||
sma
==
IPC_NOID
)
continue
;
continue
;
if
(
sma
->
sem_perm
.
seq
!=
u
->
semid
/
SEMMNI
)
if
(
sma
->
sem_perm
.
seq
!=
(
unsigned
int
)
u
->
semid
/
SEMMNI
)
continue
;
continue
;
for
(
unp
=
&
sma
->
undo
;
(
un
=
*
unp
);
unp
=
&
un
->
id_next
)
{
for
(
unp
=
&
sma
->
undo
;
(
un
=
*
unp
);
unp
=
&
un
->
id_next
)
{
if
(
u
==
un
)
if
(
u
==
un
)
...
@@ -483,7 +488,7 @@ void sem_exit (void)
...
@@ -483,7 +488,7 @@ void sem_exit (void)
if
(
!
un
->
semadj
)
if
(
!
un
->
semadj
)
continue
;
continue
;
while
(
1
)
{
while
(
1
)
{
if
(
sma
->
sem_perm
.
seq
!=
un
->
semid
/
SEMMNI
)
if
(
sma
->
sem_perm
.
seq
!=
(
unsigned
int
)
un
->
semid
/
SEMMNI
)
break
;
break
;
sem
=
&
sma
->
sem_base
[
un
->
sem_num
];
sem
=
&
sma
->
sem_base
[
un
->
sem_num
];
if
(
sem
->
semval
+
un
->
semadj
>=
0
)
{
if
(
sem
->
semval
+
un
->
semadj
>=
0
)
{
...
@@ -503,6 +508,6 @@ void sem_exit (void)
...
@@ -503,6 +508,6 @@ void sem_exit (void)
sem
->
semncnt
--
;
sem
->
semncnt
--
;
}
}
}
}
current
->
semun
=
NULL
;
current
->
semun
do
=
NULL
;
return
;
return
;
}
}
ipc/shm.c
View file @
a6614639
/*
/*
* linux/ipc/shm.c
* linux/ipc/shm.c
* Copyright (C) 1992, 1993 Krishna Balasubramanian
* Copyright (C) 1992, 1993 Krishna Balasubramanian
* Many improvements/fixes by Bruno Haible.
* Many improvements/fixes by Bruno Haible.
* assume user segments start at 0x0
*/
*/
#include <linux/errno.h>
#include <linux/errno.h>
#include <asm/segment.h>
#include <asm/segment.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/ipc.h>
#include <linux/ipc.h>
#include <linux/shm.h>
#include <linux/shm.h>
#include <linux/stat.h>
#include <linux/stat.h>
#include <linux/malloc.h>
#include <linux/malloc.h>
extern
int
ipcperms
(
struct
ipc_perm
*
ipcp
,
short
s
e
mflg
);
extern
int
ipcperms
(
struct
ipc_perm
*
ipcp
,
short
s
h
mflg
);
extern
unsigned
int
get_swap_page
(
void
);
extern
unsigned
int
get_swap_page
(
void
);
static
int
findkey
(
key_t
key
);
static
int
findkey
(
key_t
key
);
static
int
newseg
(
key_t
key
,
int
shmflg
,
int
size
);
static
int
newseg
(
key_t
key
,
int
shmflg
,
int
size
);
static
int
shm_map
(
struct
shm_desc
*
shmd
,
int
remap
);
static
int
shm_map
(
struct
shm_desc
*
shmd
,
int
remap
);
static
void
killseg
(
int
id
);
static
void
killseg
(
int
id
);
static
unsigned
long
shm_swap_in
(
struct
vm_area_struct
*
,
unsigned
long
);
static
unsigned
long
shm_swap_in
(
struct
vm_area_struct
*
,
unsigned
long
);
static
int
shm_tot
=
0
;
/* total number of shared memory pages */
static
int
shm_tot
=
0
;
/* total number of shared memory pages */
static
int
shm_rss
=
0
;
/* number of shared memory pages that are in memory */
static
int
shm_rss
=
0
;
/* number of shared memory pages that are in memory */
static
int
shm_swp
=
0
;
/* number of shared memory pages that are in swap */
static
int
shm_swp
=
0
;
/* number of shared memory pages that are in swap */
static
int
max_shmid
=
0
;
/* every used id is <= max_shmid */
static
int
max_shmid
=
0
;
/* every used id is <= max_shmid */
static
struct
wait_queue
*
shm_lock
=
NULL
;
static
struct
wait_queue
*
shm_lock
=
NULL
;
/* calling findkey() may need to wait */
static
struct
shmid_ds
*
shm_segs
[
SHMMNI
];
static
struct
shmid_ds
*
shm_segs
[
SHMMNI
];
static
unsigned
short
shm_seq
=
0
;
/* incremented, for recognizing stale ids */
static
unsigned
short
shm_seq
=
0
;
/* incremented, for recognizing stale ids */
...
@@ -38,31 +37,31 @@ static ulong used_segs = 0;
...
@@ -38,31 +37,31 @@ static ulong used_segs = 0;
void
shm_init
(
void
)
void
shm_init
(
void
)
{
{
int
id
;
int
id
;
for
(
id
=
0
;
id
<
SHMMNI
;
id
++
)
for
(
id
=
0
;
id
<
SHMMNI
;
id
++
)
shm_segs
[
id
]
=
(
struct
shmid_ds
*
)
IPC_UNUSED
;
shm_segs
[
id
]
=
(
struct
shmid_ds
*
)
IPC_UNUSED
;
shm_tot
=
shm_rss
=
shm_seq
=
max_shmid
=
used_segs
=
0
;
shm_tot
=
shm_rss
=
shm_seq
=
max_shmid
=
used_segs
=
0
;
shm_lock
=
NULL
;
shm_lock
=
NULL
;
return
;
return
;
}
}
static
int
findkey
(
key_t
key
)
static
int
findkey
(
key_t
key
)
{
{
int
id
;
int
id
;
struct
shmid_ds
*
shp
;
struct
shmid_ds
*
shp
;
for
(
id
=
0
;
id
<=
max_shmid
;
id
++
)
{
for
(
id
=
0
;
id
<=
max_shmid
;
id
++
)
{
while
((
shp
=
shm_segs
[
id
])
==
IPC_NOID
)
while
((
shp
=
shm_segs
[
id
])
==
IPC_NOID
)
sleep_on
(
&
shm_lock
);
sleep_on
(
&
shm_lock
);
if
(
shp
==
IPC_UNUSED
)
if
(
shp
==
IPC_UNUSED
)
continue
;
continue
;
if
(
key
==
shp
->
shm_perm
.
key
)
if
(
key
==
shp
->
shm_perm
.
key
)
return
id
;
return
id
;
}
}
return
-
1
;
return
-
1
;
}
}
/*
/*
* allocate new shmid_ds and pgtable. protected by shm_segs[id] = NOID.
* allocate new shmid_ds and pgtable. protected by shm_segs[id] = NOID.
*/
*/
static
int
newseg
(
key_t
key
,
int
shmflg
,
int
size
)
static
int
newseg
(
key_t
key
,
int
shmflg
,
int
size
)
...
@@ -75,7 +74,7 @@ static int newseg (key_t key, int shmflg, int size)
...
@@ -75,7 +74,7 @@ static int newseg (key_t key, int shmflg, int size)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
shm_tot
+
numpages
>=
SHMALL
)
if
(
shm_tot
+
numpages
>=
SHMALL
)
return
-
ENOSPC
;
return
-
ENOSPC
;
for
(
id
=
0
;
id
<
SHMMNI
;
id
++
)
for
(
id
=
0
;
id
<
SHMMNI
;
id
++
)
if
(
shm_segs
[
id
]
==
IPC_UNUSED
)
{
if
(
shm_segs
[
id
]
==
IPC_UNUSED
)
{
shm_segs
[
id
]
=
(
struct
shmid_ds
*
)
IPC_NOID
;
shm_segs
[
id
]
=
(
struct
shmid_ds
*
)
IPC_NOID
;
goto
found
;
goto
found
;
...
@@ -100,7 +99,7 @@ static int newseg (key_t key, int shmflg, int size)
...
@@ -100,7 +99,7 @@ static int newseg (key_t key, int shmflg, int size)
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
for
(
i
=
0
;
i
<
numpages
;
shp
->
shm_pages
[
i
++
]
=
0
);
for
(
i
=
0
;
i
<
numpages
;
shp
->
shm_pages
[
i
++
]
=
0
);
shm_tot
+=
numpages
;
shm_tot
+=
numpages
;
shp
->
shm_perm
.
key
=
key
;
shp
->
shm_perm
.
key
=
key
;
shp
->
shm_perm
.
mode
=
(
shmflg
&
S_IRWXUGO
);
shp
->
shm_perm
.
mode
=
(
shmflg
&
S_IRWXUGO
);
...
@@ -121,23 +120,23 @@ static int newseg (key_t key, int shmflg, int size)
...
@@ -121,23 +120,23 @@ static int newseg (key_t key, int shmflg, int size)
used_segs
++
;
used_segs
++
;
if
(
shm_lock
)
if
(
shm_lock
)
wake_up
(
&
shm_lock
);
wake_up
(
&
shm_lock
);
return
id
+
(
int
)
shm_seq
*
SHMMNI
;
return
(
unsigned
int
)
shp
->
shm_perm
.
seq
*
SHMMNI
+
id
;
}
}
int
sys_shmget
(
key_t
key
,
int
size
,
int
shmflg
)
int
sys_shmget
(
key_t
key
,
int
size
,
int
shmflg
)
{
{
struct
shmid_ds
*
shp
;
struct
shmid_ds
*
shp
;
int
id
=
0
;
int
id
=
0
;
if
(
size
<
0
||
size
>
SHMMAX
)
if
(
size
<
0
||
size
>
SHMMAX
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
key
==
IPC_PRIVATE
)
if
(
key
==
IPC_PRIVATE
)
return
newseg
(
key
,
shmflg
,
size
);
return
newseg
(
key
,
shmflg
,
size
);
if
((
id
=
findkey
(
key
))
==
-
1
)
{
if
((
id
=
findkey
(
key
))
==
-
1
)
{
if
(
!
(
shmflg
&
IPC_CREAT
))
if
(
!
(
shmflg
&
IPC_CREAT
))
return
-
ENOENT
;
return
-
ENOENT
;
return
newseg
(
key
,
shmflg
,
size
);
return
newseg
(
key
,
shmflg
,
size
);
}
}
if
((
shmflg
&
IPC_CREAT
)
&&
(
shmflg
&
IPC_EXCL
))
if
((
shmflg
&
IPC_CREAT
)
&&
(
shmflg
&
IPC_EXCL
))
return
-
EEXIST
;
return
-
EEXIST
;
shp
=
shm_segs
[
id
];
shp
=
shm_segs
[
id
];
...
@@ -147,10 +146,10 @@ int sys_shmget (key_t key, int size, int shmflg)
...
@@ -147,10 +146,10 @@ int sys_shmget (key_t key, int size, int shmflg)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
ipcperms
(
&
shp
->
shm_perm
,
shmflg
))
if
(
ipcperms
(
&
shp
->
shm_perm
,
shmflg
))
return
-
EACCES
;
return
-
EACCES
;
return
shp
->
shm_perm
.
seq
*
SHMMNI
+
id
;
return
(
unsigned
int
)
shp
->
shm_perm
.
seq
*
SHMMNI
+
id
;
}
}
/*
/*
* Only called after testing nattch and SHM_DEST.
* Only called after testing nattch and SHM_DEST.
* Here pages, pgtable and shmid_ds are freed.
* Here pages, pgtable and shmid_ds are freed.
*/
*/
...
@@ -166,20 +165,20 @@ static void killseg (int id)
...
@@ -166,20 +165,20 @@ static void killseg (int id)
return
;
return
;
}
}
shp
->
shm_perm
.
seq
++
;
/* for shmat */
shp
->
shm_perm
.
seq
++
;
/* for shmat */
numpages
=
shp
->
shm_npages
;
shm_seq
=
(
shm_seq
+
1
)
%
((
unsigned
)(
1
<<
31
)
/
SHMMNI
);
/* increment, but avoid overflow */
shm_seq
++
;
shm_segs
[
id
]
=
(
struct
shmid_ds
*
)
IPC_UNUSED
;
shm_segs
[
id
]
=
(
struct
shmid_ds
*
)
IPC_UNUSED
;
used_segs
--
;
used_segs
--
;
if
(
id
==
max_shmid
)
if
(
id
==
max_shmid
)
while
(
max_shmid
&&
(
shm_segs
[
--
max_shmid
]
==
IPC_UNUSED
));
while
(
max_shmid
&&
(
shm_segs
[
--
max_shmid
]
==
IPC_UNUSED
));
if
(
!
shp
->
shm_pages
)
{
if
(
!
shp
->
shm_pages
)
{
printk
(
"shm nono: killseg shp->pages=NULL. id=%d
\n
"
,
id
);
printk
(
"shm nono: killseg shp->pages=NULL. id=%d
\n
"
,
id
);
return
;
return
;
}
}
for
(
i
=
0
;
i
<
numpages
;
i
++
)
{
numpages
=
shp
->
shm_npages
;
for
(
i
=
0
;
i
<
numpages
;
i
++
)
{
if
(
!
(
page
=
shp
->
shm_pages
[
i
]))
if
(
!
(
page
=
shp
->
shm_pages
[
i
]))
continue
;
continue
;
if
(
page
&
1
)
{
if
(
page
&
PAGE_PRESENT
)
{
free_page
(
page
&
PAGE_MASK
);
free_page
(
page
&
PAGE_MASK
);
shm_rss
--
;
shm_rss
--
;
}
else
{
}
else
{
...
@@ -195,10 +194,11 @@ static void killseg (int id)
...
@@ -195,10 +194,11 @@ static void killseg (int id)
int
sys_shmctl
(
int
shmid
,
int
cmd
,
struct
shmid_ds
*
buf
)
int
sys_shmctl
(
int
shmid
,
int
cmd
,
struct
shmid_ds
*
buf
)
{
{
struct
shmid_ds
*
shp
,
tbuf
;
struct
shmid_ds
tbuf
;
struct
shmid_ds
*
shp
;
struct
ipc_perm
*
ipcp
;
struct
ipc_perm
*
ipcp
;
int
id
,
err
;
int
id
,
err
;
if
(
cmd
<
0
||
shmid
<
0
)
if
(
cmd
<
0
||
shmid
<
0
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
cmd
==
IPC_SET
)
{
if
(
cmd
==
IPC_SET
)
{
...
@@ -211,7 +211,7 @@ int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
...
@@ -211,7 +211,7 @@ int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
}
}
switch
(
cmd
)
{
/* replace with proc interface ? */
switch
(
cmd
)
{
/* replace with proc interface ? */
case
IPC_INFO
:
case
IPC_INFO
:
{
{
struct
shminfo
shminfo
;
struct
shminfo
shminfo
;
if
(
!
buf
)
if
(
!
buf
)
...
@@ -227,15 +227,15 @@ int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
...
@@ -227,15 +227,15 @@ int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
memcpy_tofs
(
buf
,
&
shminfo
,
sizeof
(
struct
shminfo
));
memcpy_tofs
(
buf
,
&
shminfo
,
sizeof
(
struct
shminfo
));
return
max_shmid
;
return
max_shmid
;
}
}
case
SHM_INFO
:
case
SHM_INFO
:
{
{
struct
shm_info
shm_info
;
struct
shm_info
shm_info
;
if
(
!
buf
)
if
(
!
buf
)
return
-
EFAULT
;
return
-
EFAULT
;
err
=
verify_area
(
VERIFY_WRITE
,
buf
,
sizeof
(
shm_info
));
err
=
verify_area
(
VERIFY_WRITE
,
buf
,
sizeof
(
shm_info
));
if
(
err
)
if
(
err
)
return
err
;
return
err
;
shm_info
.
used_ids
=
used_segs
;
shm_info
.
used_ids
=
used_segs
;
shm_info
.
shm_rss
=
shm_rss
;
shm_info
.
shm_rss
=
shm_rss
;
shm_info
.
shm_tot
=
shm_tot
;
shm_info
.
shm_tot
=
shm_tot
;
shm_info
.
shm_swp
=
shm_swp
;
shm_info
.
shm_swp
=
shm_swp
;
...
@@ -247,7 +247,7 @@ int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
...
@@ -247,7 +247,7 @@ int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
case
SHM_STAT
:
case
SHM_STAT
:
if
(
!
buf
)
if
(
!
buf
)
return
-
EFAULT
;
return
-
EFAULT
;
err
=
verify_area
(
VERIFY_WRITE
,
buf
,
sizeof
(
*
shp
));
err
=
verify_area
(
VERIFY_WRITE
,
buf
,
sizeof
(
*
buf
));
if
(
err
)
if
(
err
)
return
err
;
return
err
;
if
(
shmid
>
max_shmid
)
if
(
shmid
>
max_shmid
)
...
@@ -257,18 +257,26 @@ int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
...
@@ -257,18 +257,26 @@ int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
ipcperms
(
&
shp
->
shm_perm
,
S_IRUGO
))
if
(
ipcperms
(
&
shp
->
shm_perm
,
S_IRUGO
))
return
-
EACCES
;
return
-
EACCES
;
id
=
shmid
+
shp
->
shm_perm
.
seq
*
SHMMNI
;
id
=
(
unsigned
int
)
shp
->
shm_perm
.
seq
*
SHMMNI
+
shmid
;
memcpy_tofs
(
buf
,
shp
,
sizeof
(
*
shp
));
tbuf
.
shm_perm
=
shp
->
shm_perm
;
tbuf
.
shm_segsz
=
shp
->
shm_segsz
;
tbuf
.
shm_atime
=
shp
->
shm_atime
;
tbuf
.
shm_dtime
=
shp
->
shm_dtime
;
tbuf
.
shm_ctime
=
shp
->
shm_ctime
;
tbuf
.
shm_cpid
=
shp
->
shm_cpid
;
tbuf
.
shm_lpid
=
shp
->
shm_lpid
;
tbuf
.
shm_nattch
=
shp
->
shm_nattch
;
memcpy_tofs
(
buf
,
&
tbuf
,
sizeof
(
*
buf
));
return
id
;
return
id
;
}
}
shp
=
shm_segs
[
id
=
shmid
%
SHMMNI
];
shp
=
shm_segs
[
id
=
(
unsigned
int
)
shmid
%
SHMMNI
];
if
(
shp
==
IPC_UNUSED
||
shp
==
IPC_NOID
)
if
(
shp
==
IPC_UNUSED
||
shp
==
IPC_NOID
)
return
-
EINVAL
;
return
-
EINVAL
;
ipcp
=
&
shp
->
shm_perm
;
if
(
shp
->
shm_perm
.
seq
!=
(
unsigned
int
)
shmid
/
SHMMNI
)
if
(
ipcp
->
seq
!=
shmid
/
SHMMNI
)
return
-
EIDRM
;
return
-
EIDRM
;
ipcp
=
&
shp
->
shm_perm
;
switch
(
cmd
)
{
switch
(
cmd
)
{
case
SHM_UNLOCK
:
case
SHM_UNLOCK
:
if
(
!
suser
())
if
(
!
suser
())
...
@@ -292,10 +300,18 @@ int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
...
@@ -292,10 +300,18 @@ int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
return
-
EACCES
;
return
-
EACCES
;
if
(
!
buf
)
if
(
!
buf
)
return
-
EFAULT
;
return
-
EFAULT
;
err
=
verify_area
(
VERIFY_WRITE
,
buf
,
sizeof
(
*
shp
));
err
=
verify_area
(
VERIFY_WRITE
,
buf
,
sizeof
(
*
buf
));
if
(
err
)
if
(
err
)
return
err
;
return
err
;
memcpy_tofs
(
buf
,
shp
,
sizeof
(
*
shp
));
tbuf
.
shm_perm
=
shp
->
shm_perm
;
tbuf
.
shm_segsz
=
shp
->
shm_segsz
;
tbuf
.
shm_atime
=
shp
->
shm_atime
;
tbuf
.
shm_dtime
=
shp
->
shm_dtime
;
tbuf
.
shm_ctime
=
shp
->
shm_ctime
;
tbuf
.
shm_cpid
=
shp
->
shm_cpid
;
tbuf
.
shm_lpid
=
shp
->
shm_lpid
;
tbuf
.
shm_nattch
=
shp
->
shm_nattch
;
memcpy_tofs
(
buf
,
&
tbuf
,
sizeof
(
*
buf
));
break
;
break
;
case
IPC_SET
:
case
IPC_SET
:
if
(
suser
()
||
current
->
euid
==
shp
->
shm_perm
.
uid
||
if
(
suser
()
||
current
->
euid
==
shp
->
shm_perm
.
uid
||
...
@@ -312,7 +328,7 @@ int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
...
@@ -312,7 +328,7 @@ int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
if
(
suser
()
||
current
->
euid
==
shp
->
shm_perm
.
uid
||
if
(
suser
()
||
current
->
euid
==
shp
->
shm_perm
.
uid
||
current
->
euid
==
shp
->
shm_perm
.
cuid
)
{
current
->
euid
==
shp
->
shm_perm
.
cuid
)
{
shp
->
shm_perm
.
mode
|=
SHM_DEST
;
shp
->
shm_perm
.
mode
|=
SHM_DEST
;
if
(
shp
->
shm_nattch
<=
0
)
if
(
shp
->
shm_nattch
<=
0
)
killseg
(
id
);
killseg
(
id
);
break
;
break
;
}
}
...
@@ -334,9 +350,9 @@ static int shm_map (struct shm_desc *shmd, int remap)
...
@@ -334,9 +350,9 @@ static int shm_map (struct shm_desc *shmd, int remap)
unsigned
long
*
page_table
;
unsigned
long
*
page_table
;
unsigned
long
tmp
,
shm_sgn
;
unsigned
long
tmp
,
shm_sgn
;
unsigned
long
page_dir
=
shmd
->
task
->
tss
.
cr3
;
unsigned
long
page_dir
=
shmd
->
task
->
tss
.
cr3
;
/* check that the range is unmapped and has page_tables */
/* check that the range is unmapped and has page_tables */
for
(
tmp
=
shmd
->
start
;
tmp
<
shmd
->
end
;
tmp
+=
PAGE_SIZE
)
{
for
(
tmp
=
shmd
->
start
;
tmp
<
shmd
->
end
;
tmp
+=
PAGE_SIZE
)
{
page_table
=
PAGE_DIR_OFFSET
(
page_dir
,
tmp
);
page_table
=
PAGE_DIR_OFFSET
(
page_dir
,
tmp
);
if
(
*
page_table
&
PAGE_PRESENT
)
{
if
(
*
page_table
&
PAGE_PRESENT
)
{
page_table
=
(
ulong
*
)
(
PAGE_MASK
&
*
page_table
);
page_table
=
(
ulong
*
)
(
PAGE_MASK
&
*
page_table
);
...
@@ -353,10 +369,10 @@ static int shm_map (struct shm_desc *shmd, int remap)
...
@@ -353,10 +369,10 @@ static int shm_map (struct shm_desc *shmd, int remap)
invalid
++
;
invalid
++
;
}
}
continue
;
continue
;
}
}
{
{
unsigned
long
new_pt
;
unsigned
long
new_pt
;
if
(
!
(
new_pt
=
get_free_page
(
GFP_KERNEL
)))
/* clearing needed? SRB. */
if
(
!
(
new_pt
=
get_free_page
(
GFP_KERNEL
)))
return
-
ENOMEM
;
return
-
ENOMEM
;
*
page_table
=
new_pt
|
PAGE_TABLE
;
*
page_table
=
new_pt
|
PAGE_TABLE
;
tmp
|=
((
PAGE_SIZE
<<
10
)
-
PAGE_SIZE
);
tmp
|=
((
PAGE_SIZE
<<
10
)
-
PAGE_SIZE
);
...
@@ -366,8 +382,8 @@ static int shm_map (struct shm_desc *shmd, int remap)
...
@@ -366,8 +382,8 @@ static int shm_map (struct shm_desc *shmd, int remap)
/* map page range */
/* map page range */
shm_sgn
=
shmd
->
shm_sgn
;
shm_sgn
=
shmd
->
shm_sgn
;
for
(
tmp
=
shmd
->
start
;
tmp
<
shmd
->
end
;
tmp
+=
PAGE_SIZE
,
for
(
tmp
=
shmd
->
start
;
tmp
<
shmd
->
end
;
tmp
+=
PAGE_SIZE
,
shm_sgn
+=
(
1
<<
SHM_IDX_SHIFT
))
{
shm_sgn
+=
(
1
<<
SHM_IDX_SHIFT
))
{
page_table
=
PAGE_DIR_OFFSET
(
page_dir
,
tmp
);
page_table
=
PAGE_DIR_OFFSET
(
page_dir
,
tmp
);
page_table
=
(
ulong
*
)
(
PAGE_MASK
&
*
page_table
);
page_table
=
(
ulong
*
)
(
PAGE_MASK
&
*
page_table
);
page_table
+=
(
tmp
>>
PAGE_SHIFT
)
&
(
PTRS_PER_PAGE
-
1
);
page_table
+=
(
tmp
>>
PAGE_SHIFT
)
&
(
PTRS_PER_PAGE
-
1
);
...
@@ -404,7 +420,7 @@ static int add_vm_area(unsigned long addr, unsigned long len, int readonly)
...
@@ -404,7 +420,7 @@ static int add_vm_area(unsigned long addr, unsigned long len, int readonly)
vma
->
vm_task
=
current
;
vma
->
vm_task
=
current
;
vma
->
vm_start
=
addr
;
vma
->
vm_start
=
addr
;
vma
->
vm_end
=
addr
+
len
;
vma
->
vm_end
=
addr
+
len
;
vma
->
vm_flags
=
VM_SHM
|
VM_MAYREAD
|
VM_MAYEXEC
|
VM_READ
|
VM_EXEC
;
vma
->
vm_flags
=
VM_SHM
|
VM_
SHARED
|
VM_
MAYREAD
|
VM_MAYEXEC
|
VM_READ
|
VM_EXEC
;
if
(
readonly
)
if
(
readonly
)
vma
->
vm_page_prot
=
PAGE_READONLY
;
vma
->
vm_page_prot
=
PAGE_READONLY
;
else
{
else
{
...
@@ -420,10 +436,9 @@ static int add_vm_area(unsigned long addr, unsigned long len, int readonly)
...
@@ -420,10 +436,9 @@ static int add_vm_area(unsigned long addr, unsigned long len, int readonly)
return
0
;
return
0
;
}
}
/*
/*
* Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists.
* Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists.
* raddr is needed to return addresses above 2Gig.
* raddr is needed to return addresses above 2Gig.
* Specific attaches are allowed over the executable....
*/
*/
int
sys_shmat
(
int
shmid
,
char
*
shmaddr
,
int
shmflg
,
ulong
*
raddr
)
int
sys_shmat
(
int
shmid
,
char
*
shmaddr
,
int
shmflg
,
ulong
*
raddr
)
{
{
...
@@ -432,17 +447,17 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
...
@@ -432,17 +447,17 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
int
err
;
int
err
;
unsigned
int
id
;
unsigned
int
id
;
unsigned
long
addr
;
unsigned
long
addr
;
if
(
shmid
<
0
)
if
(
shmid
<
0
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
raddr
)
{
if
(
raddr
)
{
err
=
verify_area
(
VERIFY_WRITE
,
raddr
,
sizeof
(
long
));
err
=
verify_area
(
VERIFY_WRITE
,
raddr
,
sizeof
(
u
long
));
if
(
err
)
if
(
err
)
return
err
;
return
err
;
}
}
shp
=
shm_segs
[
id
=
shmid
%
SHMMNI
];
shp
=
shm_segs
[
id
=
(
unsigned
int
)
shmid
%
SHMMNI
];
if
(
shp
==
IPC_UNUSED
||
shp
==
IPC_NOID
)
if
(
shp
==
IPC_UNUSED
||
shp
==
IPC_NOID
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -450,7 +465,7 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
...
@@ -450,7 +465,7 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
if
(
shmflg
&
SHM_REMAP
)
if
(
shmflg
&
SHM_REMAP
)
return
-
EINVAL
;
return
-
EINVAL
;
/* set addr below all current unspecified attaches */
/* set addr below all current unspecified attaches */
addr
=
SHM_RANGE_END
;
addr
=
SHM_RANGE_END
;
for
(
shmd
=
current
->
shm
;
shmd
;
shmd
=
shmd
->
task_next
)
{
for
(
shmd
=
current
->
shm
;
shmd
;
shmd
=
shmd
->
task_next
)
{
if
(
shmd
->
start
<
SHM_RANGE_START
)
if
(
shmd
->
start
<
SHM_RANGE_START
)
continue
;
continue
;
...
@@ -459,7 +474,7 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
...
@@ -459,7 +474,7 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
}
}
addr
=
(
addr
-
shp
->
shm_segsz
)
&
PAGE_MASK
;
addr
=
(
addr
-
shp
->
shm_segsz
)
&
PAGE_MASK
;
}
else
if
(
addr
&
(
SHMLBA
-
1
))
{
}
else
if
(
addr
&
(
SHMLBA
-
1
))
{
if
(
shmflg
&
SHM_RND
)
if
(
shmflg
&
SHM_RND
)
addr
&=
~
(
SHMLBA
-
1
);
/* round down */
addr
&=
~
(
SHMLBA
-
1
);
/* round down */
else
else
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -470,26 +485,26 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
...
@@ -470,26 +485,26 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
for
(
shmd
=
current
->
shm
;
shmd
;
shmd
=
shmd
->
task_next
)
{
for
(
shmd
=
current
->
shm
;
shmd
;
shmd
=
shmd
->
task_next
)
{
if
(
addr
>=
shmd
->
start
&&
addr
<
shmd
->
end
)
if
(
addr
>=
shmd
->
start
&&
addr
<
shmd
->
end
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
addr
+
shp
->
shm_segsz
>=
shmd
->
start
&&
if
(
addr
+
shp
->
shm_segsz
>=
shmd
->
start
&&
addr
+
shp
->
shm_segsz
<
shmd
->
end
)
addr
+
shp
->
shm_segsz
<
shmd
->
end
)
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
ipcperms
(
&
shp
->
shm_perm
,
shmflg
&
SHM_RDONLY
?
S_IRUGO
:
S_IRUGO
|
S_IWUGO
))
if
(
ipcperms
(
&
shp
->
shm_perm
,
shmflg
&
SHM_RDONLY
?
S_IRUGO
:
S_IRUGO
|
S_IWUGO
))
return
-
EACCES
;
return
-
EACCES
;
if
(
shp
->
shm_perm
.
seq
!=
shmid
/
SHMMNI
)
if
(
shp
->
shm_perm
.
seq
!=
(
unsigned
int
)
shmid
/
SHMMNI
)
return
-
EIDRM
;
return
-
EIDRM
;
shmd
=
(
struct
shm_desc
*
)
kmalloc
(
sizeof
(
*
shmd
),
GFP_KERNEL
);
shmd
=
(
struct
shm_desc
*
)
kmalloc
(
sizeof
(
*
shmd
),
GFP_KERNEL
);
if
(
!
shmd
)
if
(
!
shmd
)
return
-
ENOMEM
;
return
-
ENOMEM
;
if
((
shp
!=
shm_segs
[
id
])
||
(
shp
->
shm_perm
.
seq
!=
shmid
/
SHMMNI
))
{
if
((
shp
!=
shm_segs
[
id
])
||
(
shp
->
shm_perm
.
seq
!=
(
unsigned
int
)
shmid
/
SHMMNI
))
{
kfree
(
shmd
);
kfree
(
shmd
);
return
-
EIDRM
;
return
-
EIDRM
;
}
}
shmd
->
shm_sgn
=
(
SHM_SWP_TYPE
<<
1
)
|
(
id
<<
SHM_ID_SHIFT
)
|
shmd
->
shm_sgn
=
(
SHM_SWP_TYPE
<<
1
)
|
(
id
<<
SHM_ID_SHIFT
)
|
(
shmflg
&
SHM_RDONLY
?
SHM_READ_ONLY
:
0
);
(
shmflg
&
SHM_RDONLY
?
SHM_READ_ONLY
:
0
);
shmd
->
start
=
addr
;
shmd
->
start
=
addr
;
shmd
->
end
=
addr
+
shp
->
shm_npages
*
PAGE_SIZE
;
shmd
->
end
=
addr
+
shp
->
shm_npages
*
PAGE_SIZE
;
shmd
->
task
=
current
;
shmd
->
task
=
current
;
...
@@ -506,7 +521,7 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
...
@@ -506,7 +521,7 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
kfree
(
shmd
);
kfree
(
shmd
);
return
err
;
return
err
;
}
}
shmd
->
task_next
=
current
->
shm
;
shmd
->
task_next
=
current
->
shm
;
current
->
shm
=
shmd
;
current
->
shm
=
shmd
;
shmd
->
seg_next
=
shp
->
attaches
;
shmd
->
seg_next
=
shp
->
attaches
;
...
@@ -526,28 +541,28 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
...
@@ -526,28 +541,28 @@ int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
*/
*/
static
void
detach
(
struct
shm_desc
**
shmdp
)
static
void
detach
(
struct
shm_desc
**
shmdp
)
{
{
struct
shm_desc
*
shmd
=
*
shmdp
;
struct
shm_desc
*
shmd
=
*
shmdp
;
struct
shmid_ds
*
shp
;
struct
shmid_ds
*
shp
;
int
id
;
int
id
;
id
=
(
shmd
->
shm_sgn
>>
SHM_ID_SHIFT
)
&
SHM_ID_MASK
;
id
=
(
shmd
->
shm_sgn
>>
SHM_ID_SHIFT
)
&
SHM_ID_MASK
;
shp
=
shm_segs
[
id
];
shp
=
shm_segs
[
id
];
*
shmdp
=
shmd
->
task_next
;
*
shmdp
=
shmd
->
task_next
;
for
(
shmdp
=
&
shp
->
attaches
;
*
shmdp
;
shmdp
=
&
(
*
shmdp
)
->
seg_next
)
for
(
shmdp
=
&
shp
->
attaches
;
*
shmdp
;
shmdp
=
&
(
*
shmdp
)
->
seg_next
)
if
(
*
shmdp
==
shmd
)
{
if
(
*
shmdp
==
shmd
)
{
*
shmdp
=
shmd
->
seg_next
;
*
shmdp
=
shmd
->
seg_next
;
goto
found
;
goto
found
;
}
}
printk
(
"detach: shm segment (id=%d) attach list inconsistent
\n
"
,
id
);
printk
(
"detach: shm segment (id=%d) attach list inconsistent
\n
"
,
id
);
found:
found:
do_munmap
(
shmd
->
start
,
shp
->
shm_segsz
);
do_munmap
(
shmd
->
start
,
shp
->
shm_segsz
);
kfree
(
shmd
);
kfree
(
shmd
);
shp
->
shm_lpid
=
current
->
pid
;
shp
->
shm_lpid
=
current
->
pid
;
shp
->
shm_dtime
=
CURRENT_TIME
;
shp
->
shm_dtime
=
CURRENT_TIME
;
if
(
--
shp
->
shm_nattch
<=
0
&&
shp
->
shm_perm
.
mode
&
SHM_DEST
)
if
(
--
shp
->
shm_nattch
<=
0
&&
shp
->
shm_perm
.
mode
&
SHM_DEST
)
killseg
(
id
);
/* sleeps */
killseg
(
id
);
/* sleeps */
return
;
return
;
}
}
/*
/*
...
@@ -556,9 +571,9 @@ static void detach (struct shm_desc **shmdp)
...
@@ -556,9 +571,9 @@ static void detach (struct shm_desc **shmdp)
*/
*/
int
sys_shmdt
(
char
*
shmaddr
)
int
sys_shmdt
(
char
*
shmaddr
)
{
{
struct
shm_desc
*
shmd
,
**
shmdp
;
struct
shm_desc
*
shmd
,
**
shmdp
;
for
(
shmdp
=
&
current
->
shm
;
(
shmd
=
*
shmdp
);
shmdp
=&
shmd
->
task_next
)
{
for
(
shmdp
=
&
current
->
shm
;
(
shmd
=
*
shmdp
);
shmdp
=&
shmd
->
task_next
)
{
if
(
shmd
->
start
==
(
ulong
)
shmaddr
)
{
if
(
shmd
->
start
==
(
ulong
)
shmaddr
)
{
detach
(
shmdp
);
detach
(
shmdp
);
return
0
;
return
0
;
...
@@ -567,17 +582,17 @@ int sys_shmdt (char *shmaddr)
...
@@ -567,17 +582,17 @@ int sys_shmdt (char *shmaddr)
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/*
/*
* detach all attached segments.
* detach all attached segments.
*/
*/
void
shm_exit
(
void
)
void
shm_exit
(
void
)
{
{
while
(
current
->
shm
)
while
(
current
->
shm
)
detach
(
&
current
->
shm
);
detach
(
&
current
->
shm
);
return
;
return
;
}
}
/*
/*
* copy the parent shm descriptors and update nattch
* copy the parent shm descriptors and update nattch
* parent is stuck in fork so an attach on each segment is assured.
* parent is stuck in fork so an attach on each segment is assured.
* copy_page_tables does the mapping.
* copy_page_tables does the mapping.
...
@@ -588,17 +603,17 @@ int shm_fork (struct task_struct *p1, struct task_struct *p2)
...
@@ -588,17 +603,17 @@ int shm_fork (struct task_struct *p1, struct task_struct *p2)
struct
shmid_ds
*
shp
;
struct
shmid_ds
*
shp
;
int
id
;
int
id
;
p2
->
semun
=
NULL
;
p2
->
semun
do
=
NULL
;
p2
->
shm
=
NULL
;
p2
->
shm
=
NULL
;
if
(
!
p1
->
shm
)
if
(
!
p1
->
shm
)
return
0
;
return
0
;
for
(
shmd
=
p1
->
shm
;
shmd
;
shmd
=
shmd
->
task_next
)
{
for
(
shmd
=
p1
->
shm
;
shmd
;
shmd
=
shmd
->
task_next
)
{
tmp
=
(
struct
shm_desc
*
)
kmalloc
(
sizeof
(
*
tmp
),
GFP_KERNEL
);
tmp
=
(
struct
shm_desc
*
)
kmalloc
(
sizeof
(
*
tmp
),
GFP_KERNEL
);
if
(
!
tmp
)
{
if
(
!
tmp
)
{
while
(
new_desc
)
{
while
(
new_desc
)
{
tmp
=
new_desc
->
task_next
;
tmp
=
new_desc
->
task_next
;
kfree
(
new_desc
);
kfree
(
new_desc
);
new_desc
=
tmp
;
new_desc
=
tmp
;
}
}
free_page_tables
(
p2
);
free_page_tables
(
p2
);
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -670,7 +685,7 @@ static unsigned long shm_swap_in(struct vm_area_struct * vma, unsigned long code
...
@@ -670,7 +685,7 @@ static unsigned long shm_swap_in(struct vm_area_struct * vma, unsigned long code
}
}
shm_rss
++
;
shm_rss
++
;
shp
->
shm_pages
[
idx
]
=
page
|
(
PAGE_SHARED
|
PAGE_DIRTY
);
shp
->
shm_pages
[
idx
]
=
page
|
(
PAGE_SHARED
|
PAGE_DIRTY
);
}
else
}
else
--
current
->
mm
->
maj_flt
;
/* was incremented in do_no_page */
--
current
->
mm
->
maj_flt
;
/* was incremented in do_no_page */
done:
done:
...
@@ -683,7 +698,7 @@ static unsigned long shm_swap_in(struct vm_area_struct * vma, unsigned long code
...
@@ -683,7 +698,7 @@ static unsigned long shm_swap_in(struct vm_area_struct * vma, unsigned long code
}
}
/*
/*
* Goes through counter = (shm_rss << prio) present shm pages.
* Goes through counter = (shm_rss << prio) present shm pages.
*/
*/
static
unsigned
long
swap_id
=
0
;
/* currently being swapped */
static
unsigned
long
swap_id
=
0
;
/* currently being swapped */
static
unsigned
long
swap_idx
=
0
;
/* next to swap */
static
unsigned
long
swap_idx
=
0
;
/* next to swap */
...
@@ -704,7 +719,7 @@ int shm_swap (int prio)
...
@@ -704,7 +719,7 @@ int shm_swap (int prio)
check_id:
check_id:
shp
=
shm_segs
[
swap_id
];
shp
=
shm_segs
[
swap_id
];
if
(
shp
==
IPC_UNUSED
||
shp
==
IPC_NOID
||
shp
->
shm_perm
.
mode
&
SHM_LOCKED
)
{
if
(
shp
==
IPC_UNUSED
||
shp
==
IPC_NOID
||
shp
->
shm_perm
.
mode
&
SHM_LOCKED
)
{
swap_idx
=
0
;
swap_idx
=
0
;
if
(
++
swap_id
>
max_shmid
)
if
(
++
swap_id
>
max_shmid
)
swap_id
=
0
;
swap_id
=
0
;
goto
check_id
;
goto
check_id
;
...
@@ -712,8 +727,8 @@ int shm_swap (int prio)
...
@@ -712,8 +727,8 @@ int shm_swap (int prio)
id
=
swap_id
;
id
=
swap_id
;
check_table:
check_table:
idx
=
swap_idx
++
;
idx
=
swap_idx
++
;
if
(
idx
>=
shp
->
shm_npages
)
{
if
(
idx
>=
shp
->
shm_npages
)
{
swap_idx
=
0
;
swap_idx
=
0
;
if
(
++
swap_id
>
max_shmid
)
if
(
++
swap_id
>
max_shmid
)
swap_id
=
0
;
swap_id
=
0
;
...
@@ -743,12 +758,12 @@ int shm_swap (int prio)
...
@@ -743,12 +758,12 @@ int shm_swap (int prio)
continue
;
continue
;
}
}
pte
=
PAGE_DIR_OFFSET
(
shmd
->
task
->
tss
.
cr3
,
tmp
);
pte
=
PAGE_DIR_OFFSET
(
shmd
->
task
->
tss
.
cr3
,
tmp
);
if
(
!
(
*
pte
&
1
))
{
if
(
!
(
*
pte
&
PAGE_PRESENT
))
{
printk
(
"shm_swap: bad pgtbl! id=%ld start=%lx idx=%ld
\n
"
,
printk
(
"shm_swap: bad pgtbl! id=%ld start=%lx idx=%ld
\n
"
,
id
,
shmd
->
start
,
idx
);
id
,
shmd
->
start
,
idx
);
*
pte
=
0
;
*
pte
=
0
;
continue
;
continue
;
}
}
pte
=
(
ulong
*
)
(
PAGE_MASK
&
*
pte
);
pte
=
(
ulong
*
)
(
PAGE_MASK
&
*
pte
);
pte
+=
((
tmp
>>
PAGE_SHIFT
)
&
(
PTRS_PER_PAGE
-
1
));
pte
+=
((
tmp
>>
PAGE_SHIFT
)
&
(
PTRS_PER_PAGE
-
1
));
tmp
=
*
pte
;
tmp
=
*
pte
;
...
@@ -756,7 +771,7 @@ int shm_swap (int prio)
...
@@ -756,7 +771,7 @@ int shm_swap (int prio)
continue
;
continue
;
if
(
tmp
&
PAGE_ACCESSED
)
{
if
(
tmp
&
PAGE_ACCESSED
)
{
*
pte
&=
~
PAGE_ACCESSED
;
*
pte
&=
~
PAGE_ACCESSED
;
continue
;
continue
;
}
}
tmp
=
shmd
->
shm_sgn
|
idx
<<
SHM_IDX_SHIFT
;
tmp
=
shmd
->
shm_sgn
|
idx
<<
SHM_IDX_SHIFT
;
*
pte
=
tmp
;
*
pte
=
tmp
;
...
@@ -765,7 +780,7 @@ int shm_swap (int prio)
...
@@ -765,7 +780,7 @@ int shm_swap (int prio)
invalid
++
;
invalid
++
;
}
}
if
(
mem_map
[
MAP_NR
(
page
)]
!=
1
)
if
(
mem_map
[
MAP_NR
(
page
)]
!=
1
)
goto
check_table
;
goto
check_table
;
page
&=
PAGE_MASK
;
page
&=
PAGE_MASK
;
shp
->
shm_pages
[
idx
]
=
swap_nr
;
shp
->
shm_pages
[
idx
]
=
swap_nr
;
...
...
ipc/util.c
View file @
a6614639
...
@@ -13,7 +13,7 @@
...
@@ -13,7 +13,7 @@
#include <linux/stat.h>
#include <linux/stat.h>
void
ipc_init
(
void
);
void
ipc_init
(
void
);
asmlinkage
int
sys_ipc
(
uint
call
,
int
first
,
int
second
,
int
third
,
void
*
ptr
);
asmlinkage
int
sys_ipc
(
uint
call
,
int
first
,
int
second
,
int
third
,
void
*
ptr
);
#ifdef CONFIG_SYSVIPC
#ifdef CONFIG_SYSVIPC
...
@@ -21,16 +21,16 @@ int ipcperms (struct ipc_perm *ipcp, short flag);
...
@@ -21,16 +21,16 @@ int ipcperms (struct ipc_perm *ipcp, short flag);
extern
void
sem_init
(
void
),
msg_init
(
void
),
shm_init
(
void
);
extern
void
sem_init
(
void
),
msg_init
(
void
),
shm_init
(
void
);
extern
int
sys_semget
(
key_t
key
,
int
nsems
,
int
semflg
);
extern
int
sys_semget
(
key_t
key
,
int
nsems
,
int
semflg
);
extern
int
sys_semop
(
int
semid
,
struct
sembuf
*
sops
,
unsigned
nsops
);
extern
int
sys_semop
(
int
semid
,
struct
sembuf
*
sops
,
unsigned
nsops
);
extern
int
sys_semctl
(
int
semid
,
int
semnum
,
int
cmd
,
void
*
arg
);
extern
int
sys_semctl
(
int
semid
,
int
semnum
,
int
cmd
,
union
semun
arg
);
extern
int
sys_msgget
(
key_t
key
,
int
msgflg
);
extern
int
sys_msgget
(
key_t
key
,
int
msgflg
);
extern
int
sys_msgsnd
(
int
msqid
,
struct
msgbuf
*
msgp
,
int
msgsz
,
int
msgflg
);
extern
int
sys_msgsnd
(
int
msqid
,
struct
msgbuf
*
msgp
,
int
msgsz
,
int
msgflg
);
extern
int
sys_msgrcv
(
int
msqid
,
struct
msgbuf
*
msgp
,
int
msgsz
,
long
msgtyp
,
extern
int
sys_msgrcv
(
int
msqid
,
struct
msgbuf
*
msgp
,
int
msgsz
,
long
msgtyp
,
int
msgflg
);
int
msgflg
);
extern
int
sys_msgctl
(
int
msqid
,
int
cmd
,
struct
msqid_ds
*
buf
);
extern
int
sys_msgctl
(
int
msqid
,
int
cmd
,
struct
msqid_ds
*
buf
);
extern
int
sys_shmctl
(
int
shmid
,
int
cmd
,
struct
shmid_ds
*
buf
);
extern
int
sys_shmget
(
key_t
key
,
int
size
,
int
flag
);
extern
int
sys_shmget
(
key_t
key
,
int
size
,
int
flag
);
extern
int
sys_shmat
(
int
shmid
,
char
*
shmaddr
,
int
shmflg
,
ulong
*
addr
);
extern
int
sys_shmat
(
int
shmid
,
char
*
shmaddr
,
int
shmflg
,
ulong
*
addr
);
extern
int
sys_shmdt
(
char
*
shmaddr
);
extern
int
sys_shmdt
(
char
*
shmaddr
);
extern
int
sys_shmctl
(
int
shmid
,
int
cmd
,
struct
shmid_ds
*
buf
);
void
ipc_init
(
void
)
void
ipc_init
(
void
)
{
{
...
@@ -71,8 +71,16 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr)
...
@@ -71,8 +71,16 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr)
return
sys_semop
(
first
,
(
struct
sembuf
*
)
ptr
,
second
);
return
sys_semop
(
first
,
(
struct
sembuf
*
)
ptr
,
second
);
case
SEMGET
:
case
SEMGET
:
return
sys_semget
(
first
,
second
,
third
);
return
sys_semget
(
first
,
second
,
third
);
case
SEMCTL
:
case
SEMCTL
:
{
return
sys_semctl
(
first
,
second
,
third
,
ptr
);
union
semun
fourth
;
int
err
;
if
(
!
ptr
)
return
-
EINVAL
;
if
((
err
=
verify_area
(
VERIFY_READ
,
ptr
,
sizeof
(
long
))))
return
err
;
fourth
.
__pad
=
(
void
*
)
get_fs_long
(
ptr
);
return
sys_semctl
(
first
,
second
,
third
,
fourth
);
}
default:
default:
return
-
EINVAL
;
return
-
EINVAL
;
}
}
...
@@ -82,10 +90,13 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr)
...
@@ -82,10 +90,13 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr)
return
sys_msgsnd
(
first
,
(
struct
msgbuf
*
)
ptr
,
return
sys_msgsnd
(
first
,
(
struct
msgbuf
*
)
ptr
,
second
,
third
);
second
,
third
);
case
MSGRCV
:
{
case
MSGRCV
:
{
struct
ipc_kludge
tmp
;
struct
ipc_kludge
tmp
;
int
err
;
if
(
!
ptr
)
if
(
!
ptr
)
return
-
EINVAL
;
return
-
EINVAL
;
memcpy_fromfs
(
&
tmp
,(
struct
ipc_kludge
*
)
ptr
,
if
((
err
=
verify_area
(
VERIFY_READ
,
ptr
,
sizeof
(
tmp
))))
return
err
;
memcpy_fromfs
(
&
tmp
,(
struct
ipc_kludge
*
)
ptr
,
sizeof
(
tmp
));
sizeof
(
tmp
));
return
sys_msgrcv
(
first
,
tmp
.
msgp
,
second
,
tmp
.
msgtyp
,
return
sys_msgrcv
(
first
,
tmp
.
msgp
,
second
,
tmp
.
msgtyp
,
third
);
third
);
...
@@ -93,14 +104,13 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr)
...
@@ -93,14 +104,13 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr)
case
MSGGET
:
case
MSGGET
:
return
sys_msgget
((
key_t
)
first
,
second
);
return
sys_msgget
((
key_t
)
first
,
second
);
case
MSGCTL
:
case
MSGCTL
:
return
sys_msgctl
(
first
,
second
,
return
sys_msgctl
(
first
,
second
,
(
struct
msqid_ds
*
)
ptr
);
(
struct
msqid_ds
*
)
ptr
);
default:
default:
return
-
EINVAL
;
return
-
EINVAL
;
}
}
if
(
call
<=
SHMCTL
)
if
(
call
<=
SHMCTL
)
switch
(
call
)
{
switch
(
call
)
{
case
SHMAT
:
/* returning shmaddr > 2G will screw up */
case
SHMAT
:
return
sys_shmat
(
first
,
(
char
*
)
ptr
,
second
,
return
sys_shmat
(
first
,
(
char
*
)
ptr
,
second
,
(
ulong
*
)
third
);
(
ulong
*
)
third
);
case
SHMDT
:
case
SHMDT
:
...
@@ -108,8 +118,7 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr)
...
@@ -108,8 +118,7 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr)
case
SHMGET
:
case
SHMGET
:
return
sys_shmget
(
first
,
second
,
third
);
return
sys_shmget
(
first
,
second
,
third
);
case
SHMCTL
:
case
SHMCTL
:
return
sys_shmctl
(
first
,
second
,
return
sys_shmctl
(
first
,
second
,
(
struct
shmid_ds
*
)
ptr
);
(
struct
shmid_ds
*
)
ptr
);
default:
default:
return
-
EINVAL
;
return
-
EINVAL
;
}
}
...
...
kernel/exit.c
View file @
a6614639
...
@@ -411,7 +411,7 @@ NORET_TYPE void do_exit(long code)
...
@@ -411,7 +411,7 @@ NORET_TYPE void do_exit(long code)
intr_count
=
0
;
intr_count
=
0
;
}
}
fake_volatile:
fake_volatile:
if
(
current
->
semun
)
if
(
current
->
semun
do
)
sem_exit
();
sem_exit
();
if
(
current
->
shm
)
if
(
current
->
shm
)
shm_exit
();
shm_exit
();
...
...
kernel/ksyms.c
View file @
a6614639
...
@@ -28,6 +28,7 @@
...
@@ -28,6 +28,7 @@
#include <linux/tty.h>
#include <linux/tty.h>
#include <linux/serial.h>
#include <linux/serial.h>
#include <linux/locks.h>
#include <linux/locks.h>
#include <linux/string.h>
#ifdef CONFIG_INET
#ifdef CONFIG_INET
#include <linux/net.h>
#include <linux/net.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
...
@@ -46,7 +47,6 @@ extern void (*do_floppy)(void);
...
@@ -46,7 +47,6 @@ extern void (*do_floppy)(void);
#endif
#endif
extern
int
sys_tz
;
extern
int
sys_tz
;
extern
int
___strtok
;
extern
int
request_dma
(
unsigned
int
dmanr
,
char
*
deviceID
);
extern
int
request_dma
(
unsigned
int
dmanr
,
char
*
deviceID
);
extern
void
free_dma
(
unsigned
int
dmanr
);
extern
void
free_dma
(
unsigned
int
dmanr
);
...
@@ -92,6 +92,13 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
...
@@ -92,6 +92,13 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
X
(
open_namei
),
X
(
open_namei
),
X
(
inode_setattr
),
X
(
inode_setattr
),
X
(
inode_change_ok
),
X
(
inode_change_ok
),
X
(
generic_mmap
),
X
(
set_blocksize
),
X
(
getblk
),
X
(
bread
),
X
(
brelse
),
X
(
ll_rw_block
),
X
(
__wait_on_buffer
),
/* device registration */
/* device registration */
X
(
register_chrdev
),
X
(
register_chrdev
),
...
@@ -156,6 +163,7 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
...
@@ -156,6 +163,7 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
X
(
printk
),
X
(
printk
),
X
(
sprintf
),
X
(
sprintf
),
X
(
vsprintf
),
X
(
vsprintf
),
X
(
simple_strtoul
),
X
(
system_utsname
),
X
(
system_utsname
),
X
(
sys_call_table
),
X
(
sys_call_table
),
...
@@ -206,26 +214,16 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
...
@@ -206,26 +214,16 @@ struct symbol_table symbol_table = { 0, 0, 0, /* for stacked module support */
#endif
#endif
/* Added to make file system as module */
/* Added to make file system as module */
X
(
set_writetime
),
X
(
set_writetime
),
X
(
getblk
),
X
(
inode_setattr
),
X
(
sys_tz
),
X
(
sys_tz
),
X
(
inode_change_ok
),
X
(
__wait_on_super
),
X
(
__wait_on_super
),
X
(
file_fsync
),
X
(
file_fsync
),
X
(
simple_strtoul
),
X
(
generic_mmap
),
X
(
set_blocksize
),
X
(
clear_inode
),
X
(
clear_inode
),
X
(
refile_buffer
),
X
(
refile_buffer
),
X
(
___strtok
),
X
(
___strtok
),
X
(
brelse
),
X
(
bread
),
X
(
init_fifo
),
X
(
init_fifo
),
X
(
super_blocks
),
X
(
super_blocks
),
X
(
chrdev_inode_operations
),
X
(
chrdev_inode_operations
),
X
(
blkdev_inode_operations
),
X
(
blkdev_inode_operations
),
X
(
ll_rw_block
),
X
(
__wait_on_buffer
),
X
(
read_ahead
),
X
(
read_ahead
),
/********************************************************
/********************************************************
* Do not add anything below this line,
* Do not add anything below this line,
...
...
mm/memory.c
View file @
a6614639
...
@@ -319,7 +319,7 @@ int unmap_page_range(unsigned long from, unsigned long size)
...
@@ -319,7 +319,7 @@ int unmap_page_range(unsigned long from, unsigned long size)
for
(
pc
=
pcnt
;
pc
--
;
page_table
++
)
{
for
(
pc
=
pcnt
;
pc
--
;
page_table
++
)
{
if
((
page
=
*
page_table
)
!=
0
)
{
if
((
page
=
*
page_table
)
!=
0
)
{
*
page_table
=
0
;
*
page_table
=
0
;
if
(
1
&
page
)
{
if
(
PAGE_PRESENT
&
page
)
{
if
(
!
(
mem_map
[
MAP_NR
(
page
)]
&
MAP_PAGE_RESERVED
))
if
(
!
(
mem_map
[
MAP_NR
(
page
)]
&
MAP_PAGE_RESERVED
))
if
(
current
->
mm
->
rss
>
0
)
if
(
current
->
mm
->
rss
>
0
)
--
current
->
mm
->
rss
;
--
current
->
mm
->
rss
;
...
...
net/inet/af_inet.c
View file @
a6614639
...
@@ -624,7 +624,7 @@ static int inet_create(struct socket *sock, int protocol)
...
@@ -624,7 +624,7 @@ static int inet_create(struct socket *sock, int protocol)
sk
->
prot
=
prot
;
sk
->
prot
=
prot
;
sk
->
sleep
=
sock
->
wait
;
sk
->
sleep
=
sock
->
wait
;
sk
->
daddr
=
0
;
sk
->
daddr
=
0
;
sk
->
saddr
=
ip_my_addr
()
;
sk
->
saddr
=
0
/* ip_my_addr() */
;
sk
->
err
=
0
;
sk
->
err
=
0
;
sk
->
next
=
NULL
;
sk
->
next
=
NULL
;
sk
->
pair
=
NULL
;
sk
->
pair
=
NULL
;
...
@@ -749,6 +749,7 @@ static int inet_release(struct socket *sock, struct socket *peer)
...
@@ -749,6 +749,7 @@ static int inet_release(struct socket *sock, struct socket *peer)
/* This will destroy it. */
/* This will destroy it. */
release_sock
(
sk
);
release_sock
(
sk
);
sock
->
data
=
NULL
;
sock
->
data
=
NULL
;
sk
->
socket
=
NULL
;
return
(
0
);
return
(
0
);
}
}
...
@@ -1261,6 +1262,10 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
...
@@ -1261,6 +1262,10 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
/*
/*
* This routine must find a socket given a TCP or UDP header.
* This routine must find a socket given a TCP or UDP header.
* Everything is assumed to be in net order.
* Everything is assumed to be in net order.
*
* We give priority to more closely bound ports: if some socket
* is bound to a particular foreign address, it will get the packet
* rather than somebody listening to any address..
*/
*/
struct
sock
*
get_sock
(
struct
proto
*
prot
,
unsigned
short
num
,
struct
sock
*
get_sock
(
struct
proto
*
prot
,
unsigned
short
num
,
...
@@ -1268,6 +1273,8 @@ struct sock *get_sock(struct proto *prot, unsigned short num,
...
@@ -1268,6 +1273,8 @@ struct sock *get_sock(struct proto *prot, unsigned short num,
unsigned
short
rnum
,
unsigned
long
laddr
)
unsigned
short
rnum
,
unsigned
long
laddr
)
{
{
struct
sock
*
s
;
struct
sock
*
s
;
struct
sock
*
result
=
NULL
;
int
badness
=
-
1
;
unsigned
short
hnum
;
unsigned
short
hnum
;
hnum
=
ntohs
(
num
);
hnum
=
ntohs
(
num
);
...
@@ -1284,21 +1291,41 @@ struct sock *get_sock(struct proto *prot, unsigned short num,
...
@@ -1284,21 +1291,41 @@ struct sock *get_sock(struct proto *prot, unsigned short num,
for
(
s
=
prot
->
sock_array
[
hnum
&
(
SOCK_ARRAY_SIZE
-
1
)];
for
(
s
=
prot
->
sock_array
[
hnum
&
(
SOCK_ARRAY_SIZE
-
1
)];
s
!=
NULL
;
s
=
s
->
next
)
s
!=
NULL
;
s
=
s
->
next
)
{
{
int
score
=
0
;
if
(
s
->
num
!=
hnum
)
if
(
s
->
num
!=
hnum
)
continue
;
continue
;
if
(
s
->
dead
&&
(
s
->
state
==
TCP_CLOSE
))
if
(
s
->
dead
&&
(
s
->
state
==
TCP_CLOSE
))
continue
;
continue
;
if
(
ip_addr_match
(
s
->
saddr
,
laddr
)
==
0
)
/* local address matches? */
continue
;
if
(
s
->
saddr
)
{
if
(
prot
==
&
udp_prot
)
if
(
s
->
saddr
!=
laddr
)
continue
;
score
++
;
}
/* remote address matches? */
if
(
s
->
daddr
)
{
if
(
s
->
daddr
!=
raddr
)
continue
;
score
++
;
}
/* remote port matches? */
if
(
s
->
dummy_th
.
dest
)
{
if
(
s
->
dummy_th
.
dest
!=
rnum
)
continue
;
score
++
;
}
/* perfect match? */
if
(
score
==
3
)
return
s
;
return
s
;
if
(
ip_addr_match
(
s
->
daddr
,
raddr
)
==
0
)
/* no, check if this is the best so far.. */
continue
;
if
(
score
<=
badness
)
if
(
s
->
dummy_th
.
dest
!=
rnum
&&
s
->
dummy_th
.
dest
!=
0
)
continue
;
continue
;
return
(
s
);
result
=
s
;
badness
=
score
;
}
}
return
(
NULL
)
;
return
result
;
}
}
static
struct
proto_ops
inet_proto_ops
=
{
static
struct
proto_ops
inet_proto_ops
=
{
...
...
net/inet/ip.c
View file @
a6614639
...
@@ -200,13 +200,6 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd
...
@@ -200,13 +200,6 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd
int
tmp
;
int
tmp
;
unsigned
long
src
;
unsigned
long
src
;
/*
* If there is no 'from' address as yet, then make it our loopback
*/
if
(
saddr
==
0
)
saddr
=
ip_my_addr
();
buff
=
skb
->
data
;
buff
=
skb
->
data
;
/*
/*
...
@@ -255,6 +248,12 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd
...
@@ -255,6 +248,12 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd
raddr
=
(
rt
==
NULL
)
?
0
:
rt
->
rt_gateway
;
raddr
=
(
rt
==
NULL
)
?
0
:
rt
->
rt_gateway
;
}
}
/*
* No source addr so make it our addr
*/
if
(
saddr
==
0
)
saddr
=
src
;
/*
/*
* No gateway so aim at the real destination
* No gateway so aim at the real destination
*/
*/
...
...
net/inet/proc.c
View file @
a6614639
...
@@ -95,7 +95,7 @@ get__netinfo(struct proto *pro, char *buffer, int format, char **start, off_t of
...
@@ -95,7 +95,7 @@ get__netinfo(struct proto *pro, char *buffer, int format, char **start, off_t of
format
==
0
?
sp
->
write_seq
-
sp
->
rcv_ack_seq
:
sp
->
rmem_alloc
,
format
==
0
?
sp
->
write_seq
-
sp
->
rcv_ack_seq
:
sp
->
rmem_alloc
,
format
==
0
?
sp
->
acked_seq
-
sp
->
copied_seq
:
sp
->
wmem_alloc
,
format
==
0
?
sp
->
acked_seq
-
sp
->
copied_seq
:
sp
->
wmem_alloc
,
timer_active
,
sp
->
timer
.
expires
,
(
unsigned
)
sp
->
retransmits
,
timer_active
,
sp
->
timer
.
expires
,
(
unsigned
)
sp
->
retransmits
,
sp
->
dead
?
0
:
SOCK_INODE
(
sp
->
socket
)
->
i_uid
);
sp
->
socket
?
SOCK_INODE
(
sp
->
socket
)
->
i_uid
:
0
);
if
(
timer_active
)
if
(
timer_active
)
add_timer
(
&
sp
->
timer
);
add_timer
(
&
sp
->
timer
);
/*
/*
...
...
net/inet/route.c
View file @
a6614639
...
@@ -542,9 +542,9 @@ struct rtable * ip_rt_route(unsigned long daddr, struct options *opt, unsigned l
...
@@ -542,9 +542,9 @@ struct rtable * ip_rt_route(unsigned long daddr, struct options *opt, unsigned l
/*
/*
* broadcast addresses can be special cases..
* broadcast addresses can be special cases..
*/
*/
if
(
rt
->
rt_flags
&
RTF_GATEWAY
)
if
((
rt
->
rt_gateway
==
0
)
&&
continue
;
(
rt
->
rt_dev
->
flags
&
IFF_BROADCAST
)
&&
if
(
(
rt
->
rt_dev
->
flags
&
IFF_BROADCAST
)
&&
(
rt
->
rt_dev
->
pa_brdaddr
==
daddr
))
(
rt
->
rt_dev
->
pa_brdaddr
==
daddr
))
break
;
break
;
}
}
...
...
net/inet/tcp.c
View file @
a6614639
...
@@ -89,6 +89,10 @@
...
@@ -89,6 +89,10 @@
* Michael Pall : Undo the last fix in tcp_read_urg() (multi URG PUSH broke rlogin).
* Michael Pall : Undo the last fix in tcp_read_urg() (multi URG PUSH broke rlogin).
* Michael Pall : Fix the multi URG PUSH problem in tcp_readable(), select() after URG works now.
* Michael Pall : Fix the multi URG PUSH problem in tcp_readable(), select() after URG works now.
* Michael Pall : recv(...,MSG_OOB) never blocks in the BSD api.
* Michael Pall : recv(...,MSG_OOB) never blocks in the BSD api.
* Alan Cox : Changed the semantics of sk->socket to
* fix a race and a signal problem with
* accept() and async I/O.
* Alan Cox : Relaxed the rules on tcp_sendto().
*
*
*
*
* To Fix:
* To Fix:
...
@@ -1227,7 +1231,7 @@ static int tcp_sendto(struct sock *sk, unsigned char *from,
...
@@ -1227,7 +1231,7 @@ static int tcp_sendto(struct sock *sk, unsigned char *from,
{
{
if
(
flags
&
~
(
MSG_OOB
|
MSG_DONTROUTE
))
if
(
flags
&
~
(
MSG_OOB
|
MSG_DONTROUTE
))
return
-
EINVAL
;
return
-
EINVAL
;
if
(
!
tcp_connected
(
sk
->
state
)
)
if
(
sk
->
state
==
TCP_CLOSE
)
return
-
ENOTCONN
;
return
-
ENOTCONN
;
if
(
addr_len
<
sizeof
(
*
addr
))
if
(
addr_len
<
sizeof
(
*
addr
))
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -2084,6 +2088,7 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
...
@@ -2084,6 +2088,7 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
newsk
->
dummy_th
.
res2
=
0
;
newsk
->
dummy_th
.
res2
=
0
;
newsk
->
acked_seq
=
skb
->
h
.
th
->
seq
+
1
;
newsk
->
acked_seq
=
skb
->
h
.
th
->
seq
+
1
;
newsk
->
copied_seq
=
skb
->
h
.
th
->
seq
;
newsk
->
copied_seq
=
skb
->
h
.
th
->
seq
;
newsk
->
socket
=
NULL
;
/*
/*
* Grab the ttl and tos values and use them
* Grab the ttl and tos values and use them
...
...
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