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
a89a2558
Commit
a89a2558
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 1.3.41
parent
c6545c79
Changes
31
Show whitespace changes
Inline
Side-by-side
Showing
31 changed files
with
1914 additions
and
1341 deletions
+1914
-1341
Makefile
Makefile
+2
-2
arch/alpha/defconfig
arch/alpha/defconfig
+11
-2
arch/alpha/kernel/head.S
arch/alpha/kernel/head.S
+0
-1
arch/alpha/kernel/setup.c
arch/alpha/kernel/setup.c
+1
-20
arch/alpha/mm/fault.c
arch/alpha/mm/fault.c
+0
-1
drivers/block/floppy.c
drivers/block/floppy.c
+7
-7
drivers/cdrom/mcd.c
drivers/cdrom/mcd.c
+67
-101
drivers/cdrom/mcdx.c
drivers/cdrom/mcdx.c
+225
-94
drivers/char/Config.in
drivers/char/Config.in
+1
-1
drivers/char/Makefile
drivers/char/Makefile
+5
-1
drivers/char/cyclades.c
drivers/char/cyclades.c
+58
-18
drivers/net/3c505.c
drivers/net/3c505.c
+16
-4
drivers/net/arcnet.c
drivers/net/arcnet.c
+774
-734
drivers/net/eth16i.c
drivers/net/eth16i.c
+0
-1
drivers/pci/pci.c
drivers/pci/pci.c
+3
-2
drivers/scsi/aic7xxx.c
drivers/scsi/aic7xxx.c
+617
-247
drivers/scsi/aic7xxx.seq
drivers/scsi/aic7xxx.seq
+14
-15
drivers/scsi/scsi.c
drivers/scsi/scsi.c
+35
-15
drivers/scsi/scsi.h
drivers/scsi/scsi.h
+1
-0
drivers/scsi/sd.c
drivers/scsi/sd.c
+6
-0
fs/ext2/super.c
fs/ext2/super.c
+2
-2
fs/msdos/inode.c
fs/msdos/inode.c
+1
-1
include/asm-alpha/system.h
include/asm-alpha/system.h
+28
-26
include/asm-i386/ioctl.h
include/asm-i386/ioctl.h
+20
-34
include/asm-i386/irq.h
include/asm-i386/irq.h
+1
-1
include/linux/mcd.h
include/linux/mcd.h
+2
-3
include/linux/mcdx.h
include/linux/mcdx.h
+11
-6
include/linux/pci.h
include/linux/pci.h
+1
-0
include/linux/tty.h
include/linux/tty.h
+1
-0
kernel/ksyms.c
kernel/ksyms.c
+2
-0
net/ipv4/proc.c
net/ipv4/proc.c
+2
-2
No files found.
Makefile
View file @
a89a2558
VERSION
=
1
PATCHLEVEL
=
3
SUBLEVEL
=
4
0
SUBLEVEL
=
4
1
ARCH
=
i386
...
...
@@ -323,5 +323,5 @@ include Rules.make
.hdepend
:
dummy
rm
-f
$@
$(AWK)
-f
scripts/depend.awk
`
find
$(HPATH)
-name
\*
.h
-print
`
>
.
$@
$(AWK)
-f
scripts/depend.awk
`
find
$(HPATH)
-name
\*
.h
!
-name
modversions.h
-print
`
>
.
$@
mv
.
$@
$@
arch/alpha/defconfig
View file @
a89a2558
...
...
@@ -6,10 +6,19 @@
# General setup
#
CONFIG_NATIVE=y
# CONFIG_ALPHA_AVANTI is not set
# CONFIG_ALPHA_JENSEN is not set
# CONFIG_ALPHA_NONAME is not set
CONFIG_ALPHA_CABRIOLET=y
# CONFIG_ALPHA_EB66 is not set
# CONFIG_ALPHA_EB66P is not set
# CONFIG_ALPHA_EB64 is not set
# CONFIG_ALPHA_EB64P is not set
# CONFIG_ALPHA_SRM is not set
CONFIG_PCI=y
CONFIG_ALPHA_APECS=y
# CONFIG_SERIAL_ECHO is not set
# CONFIG_TGA_CONSOLE is not set
CONFIG_PCI_OPTIMIZE=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
...
...
@@ -31,8 +40,8 @@ CONFIG_ST506=y
#
# CONFIG_BLK_DEV_HD is not set
CONFIG_BLK_DEV_IDE=y
# CONFIG_BLK_DEV_TRITON is not set
# CONFIG_BLK_DEV_IDECD is not set
# CONFIG_BLK_DEV_TRITON is not set
# CONFIG_BLK_DEV_XD is not set
#
...
...
@@ -43,7 +52,6 @@ CONFIG_INET=y
# CONFIG_IP_FORWARD is not set
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ACCT is not set
# CONFIG_NET_IPIP is not set
#
# (it is safe to leave these untouched)
...
...
@@ -120,6 +128,7 @@ CONFIG_DUMMY=m
CONFIG_NET_EISA=y
# CONFIG_APRICOT is not set
CONFIG_DE4X5=y
# CONFIG_ETH16 is not set
# CONFIG_ZNET is not set
# CONFIG_NET_POCKET is not set
# CONFIG_TR is not set
...
...
arch/alpha/kernel/head.S
View file @
a89a2558
...
...
@@ -9,7 +9,6 @@
#define __ASSEMBLY__
#include <asm/system.h>
#include <linux/fd.h>
#define halt .long PAL_halt
...
...
arch/alpha/kernel/setup.c
View file @
a89a2558
...
...
@@ -21,6 +21,7 @@
#include <linux/a.out.h>
#include <linux/tty.h>
#include <linux/delay.h>
#include <linux/config.h>
/* CONFIG_ALPHA_LCA etc */
#include <asm/segment.h>
#include <asm/system.h>
...
...
@@ -66,24 +67,6 @@ struct screen_info screen_info = {
16
/* orig-video-points */
};
/*
* Initialize Programmable Interval Timers with standard values. Some
* drivers depend on them being initialized (e.g., joystick driver).
*/
static
void
init_pit
(
void
)
{
outb
(
0x54
,
0x43
);
/* counter 1: refresh timer */
outb
(
0x18
,
0x41
);
outb
(
0x36
,
0x43
);
/* counter 0: system timer */
outb
(
0x00
,
0x40
);
outb
(
0x00
,
0x40
);
outb
(
0xb6
,
0x43
);
/* counter 2: speaker */
outb
(
0x31
,
0x42
);
outb
(
0x13
,
0x42
);
}
static
unsigned
long
find_end_memory
(
void
)
{
int
i
;
...
...
@@ -110,8 +93,6 @@ void setup_arch(char **cmdline_p,
{
extern
int
_end
;
init_pit
();
hwrpb
=
(
struct
hwrpb_struct
*
)(
IDENT_ADDR
+
INIT_HWRPB
->
phys_addr
);
set_hae
(
hae
.
cache
);
/* sync HAE register w/hae_cache */
...
...
arch/alpha/mm/fault.c
View file @
a89a2558
...
...
@@ -4,7 +4,6 @@
* Copyright (C) 1995 Linus Torvalds
*/
#include <linux/config.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/head.h>
...
...
drivers/block/floppy.c
View file @
a89a2558
...
...
@@ -3015,7 +3015,7 @@ static inline void clear_write_error(int drive)
CLEARSTRUCT
(
UDRWE
);
}
static
inline
int
set_geometry
(
int
cmd
,
struct
floppy_struct
*
g
,
static
inline
int
set_geometry
(
unsigned
int
cmd
,
struct
floppy_struct
*
g
,
int
drive
,
int
type
,
int
device
)
{
int
cnt
;
...
...
@@ -3114,14 +3114,14 @@ static inline int normalize_0x02xx_ioctl(int *cmd, int *size)
{
int
i
,
orig_size
,
ocmd
;
orig_size
=
IOC_SIZE
(
*
cmd
);
orig_size
=
_
IOC_SIZE
(
*
cmd
);
ocmd
=
*
cmd
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
translation_table
);
i
++
)
{
if
((
*
cmd
&
0xff3f
)
==
(
translation_table
[
i
].
newcmd
&
0xff3f
)){
*
cmd
=
translation_table
[
i
].
newcmd
;
if
(
!
orig_size
&&
IOC_SIZE
(
*
cmd
))
{
/* kernels 1.3.34 to 1.3.3
7
: */
*
size
=
IOC_SIZE
(
*
cmd
);
if
(
!
orig_size
&&
_
IOC_SIZE
(
*
cmd
))
{
/* kernels 1.3.34 to 1.3.3
9
: */
*
size
=
_
IOC_SIZE
(
*
cmd
);
DPRINT1
(
"warning: obsolete ioctl 0x%x
\n
"
,
ocmd
);
DPRINT
(
"please recompile your program
\n
"
);
/* these ioctls only existed
...
...
@@ -3132,7 +3132,7 @@ static inline int normalize_0x02xx_ioctl(int *cmd, int *size)
*/
}
else
{
*
size
=
orig_size
;
if
(
*
size
>
IOC_SIZE
(
*
cmd
))
{
if
(
*
size
>
_
IOC_SIZE
(
*
cmd
))
{
printk
(
"ioctl not yet supported
\n
"
);
return
-
EFAULT
;
}
...
...
@@ -3261,7 +3261,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
case
FDGETDRVTYP
:
outparam
=
drive_name
(
type
,
drive
);
SUPBOUND
(
size
,
strlen
(
outparam
));
SUPBOUND
(
size
,
strlen
(
outparam
)
+
1
);
break
;
IN
(
FDSETDRVPRM
,
UDP
,
dp
);
...
...
drivers/cdrom/mcd.c
View file @
a89a2558
...
...
@@ -60,20 +60,25 @@
17 June 95 Modifications By Andrew J. Kroll <ag784@freenet.buffalo.edu>
07 July 1995 Modifications by Andrew J. Kroll
0.6
8 November 95 More Modifications By Andrew J. Kroll
Media change detect now works :) That means that SuperMount and
other programs that depend on this will now work!
You are welcome in advance! You will notice, however that you don't
always get the kernel message saying "VFS: Disk change detected on
device", so I'm not sure that it's *PERFECT* but it does seem to
actually work! What else should I add?
*/
#include <linux/config.h>
*/
#ifdef MODULE
# include <linux/module.h>
#endif
#include <linux/version.h>
#include <linux/module.h>
#ifdef MODULE
# ifndef CONFIG_MODVERSIONS
char
kernel_version
[]
=
UTS_RELEASE
;
# endif
#define mcd_init init_module
#else
# define MOD_INC_USE_COUNT
# define MOD_DEC_USE_COUNT
#endif
#include <linux/errno.h>
#include <linux/signal.h>
...
...
@@ -138,16 +143,18 @@ static int mcdPresent = 0;
#endif
/* #define DOUBLE_QUICK_ONLY */
#define CURRENT_VALID \
#if LINUX_VERSION_CODE < 66338
#define CURRENT_VALID \
(CURRENT && MAJOR(CURRENT -> dev) == MAJOR_NR && CURRENT -> cmd == READ \
&& CURRENT -> sector != -1)
#else
#define CURRENT_VALID \
(CURRENT && MAJOR(CURRENT -> rq_dev) == MAJOR_NR && CURRENT -> cmd == READ \
&& CURRENT -> sector != -1)
#endif
#define MFL_STATUSorDATA (MFL_STATUS | MFL_DATA)
#define MCD_BUF_SIZ 16
static
volatile
int
mcd_transfer_is_active
;
/* Are you sleeping, Are you sleeping, Brother John, Brother John? ;) */
static
volatile
int
sleeping_for_status
;
static
char
mcd_buf
[
2048
*
MCD_BUF_SIZ
];
/* buffer for block size conversion */
static
volatile
int
mcd_buf_bn
[
MCD_BUF_SIZ
],
mcd_next_bn
;
static
volatile
int
mcd_buf_in
,
mcd_buf_out
=
-
1
;
...
...
@@ -215,89 +222,54 @@ void mcd_setup(char *str, int *ints)
#endif
/* WORK_AROUND_MITSUMI_BUG_93 */
}
/*
* Do a 'get status' command and get the result. Only use from the top half
* because it calls 'getMcdStatus' which sleeps.
*/
static
int
statusCmd
(
void
)
#if LINUX_VERSION_CODE < 66338
check_mcd_change
(
dev_t
full_dev
)
#else
check_mcd_change
(
kdev_t
full_dev
)
#endif
{
int
st
,
retry
;
int
retval
,
target
;
for
(
retry
=
0
;
retry
<
MCD_RETRY_ATTEMPTS
;
retry
++
)
{
outb
(
MCMD_GET_STATUS
,
MCDPORT
(
0
));
/* send get-status cmd */
st
=
getMcdStatus
(
MCD_STATUS_DELAY
);
if
(
st
!=
-
1
)
break
;
#if 1
/* the below is not reliable */
return
0
;
#endif
target
=
MINOR
(
full_dev
);
if
(
target
>
0
)
{
printk
(
"mcd: Mitsumi CD-ROM request error: invalid device.
\n
"
);
return
0
;
}
return
st
;
retval
=
mcdDiskChanged
;
mcdDiskChanged
=
0
;
return
retval
;
}
/*
* This detects a media change on the CD ROM.
* We need to grab the status right off the drive in here.
* Before, it ALWAYS returned a value of 0, which was not right!
* Do a 'get status' command and get the result. Only use from the top half
* because it calls 'getMcdStatus' which sleeps.
*/
static
int
check_mcd_change
(
dev_t
full_dev
)
statusCmd
(
void
)
{
int
retval
,
target
,
st
,
count
;
st
=
-
1
;
target
=
MINOR
(
full_dev
);
int
st
,
retry
;
if
(
target
>
0
)
for
(
retry
=
0
;
retry
<
MCD_RETRY_ATTEMPTS
;
retry
++
)
{
printk
(
"mcd: Mitsumi CD-ROM request error: invalid device.
\n
"
);
return
0
;
}
/*
* SOMETIMES it changes, sometimes not! Well, here we FIX that little nasty!
* All we need to do is read the status from the drive without spamming the
* kernel! In other words, this routine CANNOT sleep!
* The kernel will automagically picks up on this now.
* Devilishly sneaky it is! 8) -- AJK
*/
if
((
!
mcd_transfer_is_active
)
&&
(
!
sleeping_for_status
)
&&
(
mcd_state
==
MCD_S_IDLE
))
/* YES I'm paraniod! :) */
{
outb
(
MCMD_GET_STATUS
,
MCDPORT
(
0
));
/* send get-status cmd */
for
(
count
=
0
;
count
<
3000
;
count
++
)
/* wait for the status */
{
if
(
!
(
inb
(
MCDPORT
(
1
))
&
MFL_STATUS
))
st
=
getMcdStatus
(
MCD_STATUS_DELAY
);
if
(
st
!=
-
1
)
break
;
}
if
(
count
>=
3000
)
/* Did we time out? */
{
retval
=
mcdDiskChanged
;
/* We can just jump out of here */
mcdDiskChanged
=
0
;
/* as it's not needed all the time. */
return
retval
;
/* So we pretend nothing happened here! ;) */
}
st
=
inb
(
MCDPORT
(
0
))
&
0xFF
;
/* Read the status in... */
/* okay... here's that magic part! Muhuhuhuh...*/
if
(
st
&
MST_DSK_CHG
)
/* Devil made me do it! O];) */
{
mcdDiskChanged
=
1
;
/* Show a change. */
audioStatus
=
CDROM_AUDIO_NO_STATUS
;
/* just incase... */
tocUpToDate
=
0
;
/* Frantic laughing continues... */
mcd_invalidate_buffers
();
/* 666 wins! */
}
/* Stupid comments are fun! */
}
retval
=
mcdDiskChanged
;
/* Indicate status. */
mcdDiskChanged
=
0
;
/* Go, now. Enjoy a good beer! */
return
retval
;
/* The End. */
return
st
;
}
...
...
@@ -1217,7 +1189,7 @@ mcd_init(void)
{
int
count
;
unsigned
char
result
[
3
];
sleeping_for_status
=
0
;
if
(
mcd_port
<=
0
||
mcd_irq
<=
0
)
{
printk
(
"skip mcd_init
\n
"
);
return
-
EIO
;
...
...
@@ -1419,14 +1391,10 @@ getMcdStatus(int timeout)
McdTimeout
=
timeout
;
SET_TIMER
(
mcdStatTimer
,
1
);
sleeping_for_status
=
1
;
sleep_on
(
&
mcd_waitq
);
if
(
McdTimeout
<=
0
)
{
sleeping_for_status
=
0
;
return
-
1
;
}
sleeping_for_status
=
0
;
st
=
inb
(
MCDPORT
(
0
))
&
0xFF
;
if
(
st
==
0xFF
)
return
-
1
;
...
...
@@ -1662,13 +1630,11 @@ Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
}
#ifdef MODULE
int
init_module
(
void
)
{
return
mcd_init
();
}
void
cleanup_module
(
void
)
{
{
if
(
MOD_IN_USE
)
{
printk
(
"mcd module in use - can't remove it.
\n
"
);
return
;
}
if
((
unregister_blkdev
(
MAJOR_NR
,
"mcd"
)
==
-
EINVAL
))
{
printk
(
"What's that: can't unregister mcd
\n
"
);
return
;
...
...
drivers/cdrom/mcdx.c
View file @
a89a2558
/*
* The Mitsumi CDROM interface
* Copyright (C) 1995 Heiko Schlittermann
* VERSION: 1.
0a
* Copyright (C) 1995 Heiko Schlittermann
<heiko@lotte.sax.de>
* VERSION: 1.
3
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -34,10 +34,26 @@
#if RCS
static
const
char
*
mcdx_c_version
=
"mcdx.c,v 1.
7 1995/08/27 01:46:41
heiko Exp"
;
=
"mcdx.c,v 1.
17 1995/11/06 01:07:57
heiko Exp"
;
#endif
#include <linux/config.h>
#ifdef MODULE
#include <linux/module.h>
#endif
#include <linux/version.h>
#ifdef MODULE
#ifndef CONFIG_MODVERSIONS
char
kernel_version
[]
=
UTS_RELEASE
;
#endif
#else
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
#define MOD_IN_USE 1
#endif MODULE
#include <linux/errno.h>
#include <linux/signal.h>
...
...
@@ -56,9 +72,11 @@ static const char *mcdx_c_version
#include <linux/major.h>
#ifndef MITSUMI_X_CDROM_MAJOR
/* old kernel (doesn't know about MCDX) */
/* old kernel (doesn't know about MCDX) */
#ifndef MITSUMI_X_CDROM_MAJOR
#define MITSUMI_X_CDROM_MAJOR 20
#define DEVICE_NAME "Mitsumi CD-ROM"
#define DEVICE_NAME "mcdx"
/* #define DEVICE_INTR do_mcdx */
#define DEVICE_REQUEST do_mcdx_request
#define DEVICE_NR(device) (MINOR(device))
...
...
@@ -68,13 +86,20 @@ static const char *mcdx_c_version
#define MAJOR_NR MITSUMI_X_CDROM_MAJOR
#include <linux/blk.h>
#define mcdx_drive_map mcdx
/* for compatible parameter passing with "insmod" */
/* for compatible parameter passing with "insmod" */
#define mcdx_drive_map mcdx
#include <linux/mcdx.h>
#ifndef HZ
#error HZ not defined
#endif
/* CONSTANTS *******************************************************/
const
int
REQUEST_SIZE
=
200
;
const
int
DIRECT_SIZE
=
200
;
const
unsigned
long
ACLOSE_INHIBIT
=
800
;
/* 1/100 s of autoclose inhibit */
enum
drivemodes
{
TOC
,
DATA
,
RAW
,
COOKED
};
enum
datamodes
{
MODE0
,
MODE1
,
MODE2
};
...
...
@@ -134,6 +159,8 @@ struct s_drive_stuff {
volatile
int
introk
;
/* status of last irq operation */
volatile
int
busy
;
/* drive performs an operation */
volatile
int
lock
;
/* exclusive usage */
int
eject_sw
;
/* 1 - eject on last close (default 0) */
int
autoclose
;
/* 1 - close the door on open (default 1) */
/* cd infos */
struct
s_diskinfo
di
;
...
...
@@ -166,10 +193,10 @@ struct s_drive_stuff {
char
playcmd
;
/* play should always be single speed */
unsigned
long
changed
;
/* last jiff the media was changed */
unsigned
long
xxx
;
/* last jiff it was asked for media change */
unsigned
long
ejected
;
/* time we called the eject function */
int
users
;
/* keeps track of open/close */
int
lastsector
;
/* last block accessible */
int
errno
;
/* last operation's error */
};
...
...
@@ -180,10 +207,18 @@ struct s_drive_stuff {
changed elsewhere. */
/* declared in blk.h */
#if LINUX_VERSION_CODE < 66338
unsigned
long
mcdx_init
(
unsigned
long
mem_start
,
unsigned
long
mem_end
);
#else
int
mcdx_init
(
void
);
#endif
void
do_mcdx_request
(
void
);
#if LINUX_VERSION_CODE < 66338
int
check_mcdx_media_change
(
dev_t
);
#else
int
check_mcdx_media_change
(
kdev_t
);
#endif
/* already declared in init/main */
void
mcdx_setup
(
char
*
,
int
*
);
...
...
@@ -229,17 +264,17 @@ static int mcdx_requestmultidiskinfo(struct s_drive_stuff*, struct s_multi*, int
static
int
mcdx_requesttocdata
(
struct
s_drive_stuff
*
,
struct
s_diskinfo
*
,
int
);
static
int
mcdx_getstatus
(
struct
s_drive_stuff
*
,
int
);
static
int
mcdx_getval
(
struct
s_drive_stuff
*
,
int
to
,
int
delay
,
char
*
);
static
int
mcdx_talk
(
struct
s_drive_stuff
*
,
const
unsigned
char
*
cmd
,
size_t
,
void
*
buffer
,
size_t
size
,
unsigned
int
timeout
,
int
);
const
unsigned
char
*
cmd
,
size_t
,
void
*
buffer
,
size_t
size
,
unsigned
int
timeout
,
int
);
static
int
mcdx_readtoc
(
struct
s_drive_stuff
*
);
static
int
mcdx_playtrk
(
struct
s_drive_stuff
*
,
const
struct
cdrom_ti
*
);
static
int
mcdx_playmsf
(
struct
s_drive_stuff
*
,
const
struct
cdrom_msf
*
);
static
int
mcdx_setattentuator
(
struct
s_drive_stuff
*
,
struct
cdrom_volctrl
*
,
int
);
/* static variables ************************************************/
static
int
dummy0
;
static
int
mcdx_drive_map
[][
2
]
=
MCDX_DRIVEMAP
;
static
struct
s_drive_stuff
*
mcdx_stuffp
[
MCDX_NDRIVES
];
static
struct
s_drive_stuff
*
mcdx_irq_map
[
16
]
=
...
...
@@ -301,7 +336,7 @@ mcdx_ioctl(
||
(
ti
.
cdti_trk1
<
stuffp
->
di
.
n_first
))
return
-
EINVAL
;
if
(
ti
.
cdti_trk1
>
stuffp
->
di
.
n_last
)
ti
.
cdti_trk1
=
stuffp
->
di
.
n_last
;
TRACE
((
IOCTL
,
"ioctl() track %d to %d
\n
"
,
ti
.
cdti_trk0
,
ti
.
cdti_trk1
));
TRACE
((
PLAYTRK
,
"ioctl() track %d to %d
\n
"
,
ti
.
cdti_trk0
,
ti
.
cdti_trk1
));
return
mcdx_playtrk
(
stuffp
,
&
ti
);
}
...
...
@@ -388,20 +423,20 @@ mcdx_ioctl(
if
(
-
1
==
mcdx_requestsubqcode
(
stuffp
,
&
q
,
2
))
return
-
EIO
;
TRACE
((
IOCT
L
,
"audiostatus: %x
\n
"
,
stuffp
->
audiostatus
));
TRACE
((
SUBCHN
L
,
"audiostatus: %x
\n
"
,
stuffp
->
audiostatus
));
sub
.
cdsc_audiostatus
=
stuffp
->
audiostatus
;
sub
.
cdsc_adr
=
q
.
control
;
sub
.
cdsc_ctrl
=
q
.
control
>>
4
;
sub
.
cdsc_trk
=
bcd2uint
(
q
.
tno
);
sub
.
cdsc_ind
=
bcd2uint
(
q
.
index
);
TRACE
((
IOCT
L
,
"trk %d, ind %d
\n
"
,
TRACE
((
SUBCHN
L
,
"trk %d, ind %d
\n
"
,
sub
.
cdsc_trk
,
sub
.
cdsc_ind
));
if
(
sub
.
cdsc_format
==
CDROM_LBA
)
{
sub
.
cdsc_absaddr
.
lba
=
msf2log
(
&
q
.
dt
);
sub
.
cdsc_reladdr
.
lba
=
msf2log
(
&
q
.
tt
);
TRACE
((
IOCT
L
,
"lba: abs %d, rel %d
\n
"
,
TRACE
((
SUBCHN
L
,
"lba: abs %d, rel %d
\n
"
,
sub
.
cdsc_absaddr
.
lba
,
sub
.
cdsc_reladdr
.
lba
));
}
else
if
(
sub
.
cdsc_format
==
CDROM_MSF
)
{
...
...
@@ -411,7 +446,7 @@ mcdx_ioctl(
sub
.
cdsc_reladdr
.
msf
.
minute
=
bcd2uint
(
q
.
tt
.
minute
);
sub
.
cdsc_reladdr
.
msf
.
second
=
bcd2uint
(
q
.
tt
.
second
);
sub
.
cdsc_reladdr
.
msf
.
frame
=
bcd2uint
(
q
.
tt
.
frame
);
TRACE
((
IOCT
L
,
TRACE
((
SUBCHN
L
,
"msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d
\n
"
,
sub
.
cdsc_absaddr
.
msf
.
minute
,
sub
.
cdsc_absaddr
.
msf
.
second
,
...
...
@@ -438,7 +473,7 @@ mcdx_ioctl(
toc
.
cdth_trk0
=
stuffp
->
di
.
n_first
;
toc
.
cdth_trk1
=
stuffp
->
di
.
n_last
;
memcpy_tofs
((
void
*
)
arg
,
&
toc
,
sizeof
toc
);
TRACE
((
IOCTL
,
"ioctl() track0 = %d, track1 = %d
\n
"
,
TRACE
((
TOCHDR
,
"ioctl() track0 = %d, track1 = %d
\n
"
,
stuffp
->
di
.
n_first
,
stuffp
->
di
.
n_last
));
return
0
;
}
...
...
@@ -447,10 +482,9 @@ mcdx_ioctl(
TRACE
((
IOCTL
,
"ioctl() PAUSE
\n
"
));
if
(
stuffp
->
audiostatus
!=
CDROM_AUDIO_PLAY
)
return
-
EINVAL
;
if
(
-
1
==
mcdx_stop
(
stuffp
,
1
))
return
-
EIO
;
stuffp
->
audiostatus
=
CDROM_AUDIO_PAUSED
;
if
(
-
1
==
mcdx_requestsubqcode
(
stuffp
,
&
stuffp
->
start
,
1
))
return
-
EIO
;
stuffp
->
audiostatus
=
CDROM_AUDIO_PAUSED
;
return
0
;
}
...
...
@@ -479,7 +513,7 @@ mcdx_ioctl(
memcpy_tofs
((
void
*
)
arg
,
&
ms
,
sizeof
(
struct
cdrom_multisession
));
if
(
ms
.
addr_format
==
CDROM_MSF
)
TRACE
((
IOCTL
,
TRACE
((
MS
,
"ioctl() (%d, %02x:%02x.%02x [%02x:%02x.%02x])
\n
"
,
ms
.
xa_flag
,
ms
.
addr
.
msf
.
minute
,
...
...
@@ -490,8 +524,7 @@ mcdx_ioctl(
stuffp
->
multi
.
msf_last
.
frame
));
else
{
dummy0
=
0
;
TRACE
((
IOCTL
,
TRACE
((
MS
,
"ioctl() (%d, 0x%08x [%02x:%02x.%02x])
\n
"
,
ms
.
xa_flag
,
ms
.
addr
.
lba
,
...
...
@@ -509,11 +542,26 @@ mcdx_ioctl(
return
0
;
}
case
CDROM
VOLCTRL
:
{
TRACE
((
IOCTL
,
"ioctl() volctrl
\n
"
))
;
case
CDROM
EJECT_SW
:
{
stuffp
->
eject_sw
=
arg
;
return
0
;
}
case
CDROMVOLCTRL
:
{
int
ans
;
struct
cdrom_volctrl
volctrl
;
TRACE
((
IOCTL
,
"ioctl() VOLCTRL
\n
"
));
if
((
ans
=
verify_area
(
VERIFY_READ
,
(
void
*
)
arg
,
sizeof
(
volctrl
))))
return
ans
;
memcpy_fromfs
(
&
volctrl
,
(
char
*
)
arg
,
sizeof
(
volctrl
));
return
mcdx_setattentuator
(
stuffp
,
&
volctrl
,
1
);
}
default:
WARN
((
"ioctl(): unknown request 0x%04x
\n
"
,
cmd
));
return
-
EINVAL
;
...
...
@@ -529,20 +577,36 @@ void do_mcdx_request()
TRACE
((
REQUEST
,
"do_request()
\n
"
));
#if LINUX_VERSION_CODE < 66338
if
((
CURRENT
==
NULL
)
||
(
CURRENT
->
dev
<
0
))
{
#else
if
((
CURRENT
==
NULL
)
||
(
CURRENT
->
rq_status
==
RQ_INACTIVE
))
{
#endif
TRACE
((
REQUEST
,
"do_request() done
\n
"
));
return
;
}
#if LINUX_VERSION_CODE < 66338
stuffp
=
mcdx_stuffp
[
MINOR
(
CURRENT
->
dev
)];
#else
stuffp
=
mcdx_stuffp
[
MINOR
(
CURRENT
->
rq_dev
)];
#endif
TRACE
((
REQUEST
,
"do_request() stuffp = %p
\n
"
,
stuffp
));
INIT_REQUEST
;
#if LINUX_VERSION_CODE < 66338
dev
=
MINOR
(
CURRENT
->
dev
);
#else
dev
=
MINOR
(
CURRENT
->
rq_dev
);
#endif
if
((
dev
<
0
)
||
(
dev
>=
MCDX_NDRIVES
)
||
(
!
stuffp
->
present
))
{
#if LINUX_VERSION_CODE < 66338
WARN
((
"do_request(): bad device: 0x%04x
\n
"
,
CURRENT
->
dev
));
#else
WARN
((
"do_request(): bad device: %s
\n
"
,
kdevname
(
CURRENT
->
rq_dev
)));
#endif
end_request
(
0
);
goto
again
;
}
...
...
@@ -596,6 +660,8 @@ void do_mcdx_request()
static
int
mcdx_open
(
struct
inode
*
ip
,
struct
file
*
fp
)
/* actions done on open:
* 1) get the drives status */
{
struct
s_drive_stuff
*
stuffp
;
...
...
@@ -603,14 +669,21 @@ mcdx_open(struct inode *ip, struct file *fp)
stuffp
=
mcdx_stuffp
[
MINOR
(
ip
->
i_rdev
)];
if
(
!
stuffp
->
present
)
return
-
ENXIO
;
/* this is only done to test if the drive talks with us */
if
(
-
1
==
mcdx_getstatus
(
stuffp
,
1
))
return
-
EIO
;
/* close the door, if necessary (get the door information
from the hardware status register) */
if
(
inb
((
unsigned
int
)
stuffp
->
rreg_status
)
&
MCDX_RBIT_DOOR
)
mcdx_closedoor
(
stuffp
,
1
);
from the hardware status register).
If the last eject is too recent, an autoclose wouldn't probably
be what we want ..., if we can't read the CD after an autoclose
no further autclose's will be tried */
if
(
inb
((
unsigned
int
)
stuffp
->
rreg_status
)
&
MCDX_RBIT_DOOR
)
{
if
(
jiffies
-
stuffp
->
ejected
<
ACLOSE_INHIBIT
)
return
-
EIO
;
if
(
stuffp
->
autoclose
)
mcdx_closedoor
(
stuffp
,
1
);
else
return
-
EIO
;
}
/* if the media changed we will have to little more */
/* if the media changed we will have to
do a
little more */
if
(
stuffp
->
xxx
<
stuffp
->
changed
)
{
TRACE
((
OPENCLOSE
,
"open() media changed
\n
"
));
...
...
@@ -619,18 +692,23 @@ mcdx_open(struct inode *ip, struct file *fp)
talk() will detect a media change ... (I think, config()
is the reason. */
/*
TRACE((OPENCLOSE, "open() hardware reset\n"));
if (-1 == mcdx_reset(stuffp, HARD, 1)) return -EIO;
*/
stuffp
->
audiostatus
=
CDROM_AUDIO_INVALID
;
/* get the multisession information */
{
int
ans
;
TRACE
((
OPENCLOSE
,
"open() Request multisession info
\n
"
));
if
(
-
1
==
mcdx_requestmultidiskinfo
(
stuffp
,
&
stuffp
->
multi
,
6
))
ans
=
mcdx_requestmultidiskinfo
(
stuffp
,
&
stuffp
->
multi
,
6
);
if
(
ans
==
-
1
)
{
stuffp
->
autoclose
=
0
;
mcdx_eject
(
stuffp
,
1
);
return
-
EIO
;
}
/* we succeeded, so on next open(2) we could try auto close
again */
stuffp
->
autoclose
=
1
;
if
(
stuffp
->
multi
.
multi
>
2
)
WARN
((
"open() unknown multisession value (%d)
\n
"
,
stuffp
->
multi
.
multi
));
...
...
@@ -743,23 +821,36 @@ mcdx_close(struct inode *ip, struct file *fp)
/* invalidate_inodes(ip->i_rdev); */
invalidate_buffers
(
ip
->
i_rdev
);
if
(
-
1
==
mcdx_lockdoor
(
stuffp
,
0
,
1
))
printk
(
MCDX
": Cannot unlock the door
\n
"
);
if
(
-
1
==
mcdx_lockdoor
(
stuffp
,
0
,
3
))
INFO
((
"close() Cannot unlock the door
\n
"
));
/* eject if wished */
if
(
stuffp
->
eject_sw
)
mcdx_eject
(
stuffp
,
1
);
}
MOD_DEC_USE_COUNT
;
return
;
}
#if LINUX_VERSION_CODE < 66338
int
check_mcdx_media_change
(
dev_t
full_dev
)
#else
int
check_mcdx_media_change
(
kdev_t
full_dev
)
#endif
/* Return: 1 if media changed since last call to
this function
0 else
Setting flag to 0 resets the changed state. */
{
#if LINUX_VERSION_CODE < 66338
INFO
((
"check_mcdx_media_change called for device %x
\n
"
,
full_dev
));
#else
INFO
((
"check_mcdx_media_change called for device %s
\n
"
,
kdevname
(
full_dev
)));
#endif
return
0
;
}
...
...
@@ -813,8 +904,8 @@ mcdx_intr(int irq, struct pt_regs* regs)
stuffp
=
mcdx_irq_map
[
irq
];
if
(
!
stuffp
->
busy
)
{
INFO
((
"intr() unexpected interrupt @ irq %d
\n
"
,
irq
));
if
(
stuffp
==
NULL
||
!
stuffp
->
busy
)
{
TRACE
((
IRQ
,
"intr() unexpected interrupt @ irq %d
\n
"
,
irq
));
return
;
}
...
...
@@ -825,8 +916,8 @@ mcdx_intr(int irq, struct pt_regs* regs)
irq
,
x
,
inb
((
unsigned
int
)
stuffp
->
rreg_data
)));
else
{
dummy0
=
0
;
TRACE
((
IRQ
,
"irq() irq %d ok, status %02x
\n
"
,
irq
,
x
));
}
stuffp
->
busy
=
0
;
wake_up_interruptible
(
&
stuffp
->
busyq
);
...
...
@@ -841,12 +932,16 @@ mcdx_talk (
unsigned
int
timeout
,
int
tries
)
/* Send a command to the drive, wait for the result.
* returns -1 on timeout, drive status otherwise
* If buffer is not zero, the result (length size) is stored there.
* If buffer is zero the size should be the number of bytes to read
* from the drive. These bytes are discarded.
*/
{
char
c
;
int
st
;
char
c
;
int
disgard
;
if
(
!
buffer
||
size
==
0
)
buffer
=
&
c
,
size
=
1
;
if
((
disgard
=
(
buffer
==
NULL
)))
buffer
=
&
c
;
while
(
stuffp
->
lock
)
interruptible_sleep_on
(
&
stuffp
->
lockq
);
...
...
@@ -881,18 +976,20 @@ mcdx_talk (
/* get the status byte */
if
(
-
1
==
mcdx_getval
(
stuffp
,
timeout
,
0
,
bp
))
{
WARN
((
"talk() %02x timed out (status), %d tr%s left
\n
"
,
INFO
((
"talk() %02x timed out (status), %d tr%s left
\n
"
,
cmd
[
0
],
tries
-
1
,
tries
==
2
?
"y"
:
"ies"
));
continue
;
}
st
=
*
bp
++
;
st
=
*
bp
;
sz
--
;
if
(
!
disgard
)
bp
++
;
TRACE
((
TALK
,
"talk() got status 0x%02x
\n
"
,
st
));
/* command error? */
if
(
e_cmderr
(
st
))
{
WARN
((
"command error %02x (%d)
\n
"
,
cmd
[
0
],
cmdlen
));
WARN
((
"command error cmd = %02x %s
\n
"
,
cmd
[
0
],
cmdlen
>
1
?
"..."
:
""
));
st
=
-
1
;
continue
;
}
...
...
@@ -901,6 +998,9 @@ mcdx_talk (
if
(
stuffp
->
audiostatus
==
CDROM_AUDIO_INVALID
)
stuffp
->
audiostatus
=
e_audiobusy
(
st
)
?
CDROM_AUDIO_PLAY
:
CDROM_AUDIO_NO_STATUS
;
else
if
(
stuffp
->
audiostatus
==
CDROM_AUDIO_PLAY
&&
e_audiobusy
(
st
)
==
0
)
stuffp
->
audiostatus
=
CDROM_AUDIO_COMPLETED
;
/* media change? */
if
(
e_changed
(
st
))
{
...
...
@@ -910,18 +1010,17 @@ mcdx_talk (
/* now actually get the data */
while
(
sz
--
)
{
if
(
-
1
==
mcdx_getval
(
stuffp
,
timeout
,
-
1
,
bp
++
))
{
WARN
((
"talk() %02x timed out (data), %d tr%s left
\n
"
,
if
(
-
1
==
mcdx_getval
(
stuffp
,
timeout
,
-
1
,
bp
))
{
INFO
((
"talk() %02x timed out (data), %d tr%s left
\n
"
,
cmd
[
0
],
tries
-
1
,
tries
==
2
?
"y"
:
"ies"
));
st
=
-
1
;
break
;
}
if
(
!
disgard
)
bp
++
;
TRACE
((
TALK
,
"talk() got 0x%02x
\n
"
,
*
(
bp
-
1
)));
}
}
#if QUIET == 0
if
(
!
tries
&&
st
==
-
1
)
INFO
((
"talk() giving up
\n
"
));
#endif
if
(
!
tries
&&
st
==
-
1
)
WARN
((
"talk() giving up
\n
"
));
stuffp
->
lock
=
0
;
wake_up_interruptible
(
&
stuffp
->
lockq
);
...
...
@@ -938,7 +1037,11 @@ int init_module(void)
int
i
;
int
drives
=
0
;
#if LINUX_VERSION_CODE < 66338
mcdx_init
(
0
,
0
);
#else
mcdx_init
();
#endif
for
(
i
=
0
;
i
<
MCDX_NDRIVES
;
i
++
)
{
if
(
mcdx_stuffp
[
i
])
{
TRACE
((
INIT
,
"init_module() drive %d stuff @ %p
\n
"
,
...
...
@@ -950,6 +1053,7 @@ int init_module(void)
if
(
!
drives
)
return
-
EIO
;
register_symtab
(
0
);
return
0
;
}
...
...
@@ -1009,12 +1113,18 @@ void warn(const char* fmt, ...)
}
#if LINUX_VERSION_CODE < 66338
unsigned
long
mcdx_init
(
unsigned
long
mem_start
,
unsigned
long
mem_end
)
#else
int
mcdx_init
(
void
)
#endif
{
int
drive
;
INFO
((
": Version 1.0a "
"mcdx.c,v 1.7 1995/08/27 01:46:41 heiko Exp
\n
"
));
WARN
((
"Version 1.3 "
"mcdx.c,v 1.17 1995/11/06 01:07:57 heiko Exp
\n
"
));
INFO
((
": Version 1.3 "
"mcdx.c,v 1.17 1995/11/06 01:07:57 heiko Exp
\n
"
));
/* zero the pointer array */
for
(
drive
=
0
;
drive
<
MCDX_NDRIVES
;
drive
++
)
...
...
@@ -1030,16 +1140,24 @@ int mcdx_init(void)
TRACE
((
INIT
,
"init() try drive %d
\n
"
,
drive
));
#if defined(MODULE) || LINUX_VERSION_CODE > 66338
TRACE
((
INIT
,
"kmalloc space for stuffpt's
\n
"
));
TRACE
((
MALLOC
,
"init() malloc %d bytes
\n
"
,
size
));
if
(
!
(
stuffp
=
kmalloc
(
size
,
GFP_KERNEL
)))
{
WARN
((
"init() malloc failed
\n
"
));
break
;
}
#else
TRACE
((
INIT
,
"adjust mem_start
\n
"
));
stuffp
=
(
struct
s_drive_stuff
*
)
mem_start
;
mem_start
+=
size
;
#endif
TRACE
((
INIT
,
"init() got %d bytes for drive stuff @ %p
\n
"
,
sizeof
(
*
stuffp
),
stuffp
));
/*
zero the stuff
*/
/*
set default values
*/
memset
(
stuffp
,
0
,
sizeof
(
*
stuffp
));
stuffp
->
autoclose
=
1
;
/* close the door on open(2) */
stuffp
->
present
=
0
;
/* this should be 0 already */
stuffp
->
toc
=
NULL
;
/* this should be NULL already */
...
...
@@ -1165,7 +1283,11 @@ int mcdx_init(void)
TRACE
((
INIT
,
"init() mcdx_stuffp[%d] = %p
\n
"
,
drive
,
stuffp
));
}
#if MODULE || LINUX_VERSION_CODE > 66338
return
0
;
#else
return
mem_start
;
#endif
}
...
...
@@ -1210,25 +1332,17 @@ static int mcdx_transfer(struct s_drive_stuff *stuffp,
current
->
timeout
=
jiffies
+
5
*
HZ
;
while
(
stuffp
->
busy
)
{
interruptible_sleep_on
(
&
stuffp
->
busyq
);
if
((
sig
=
(
current
->
signal
&&
~
current
->
blocked
))
||
(
to
=
(
current
->
timeout
==
0
)))
{
break
;
}
}
current
->
timeout
=
0
;
/* test for possible errors */
if
(((
stuffp
->
busy
==
0
)
&&
!
stuffp
->
introk
)
||
sig
||
to
)
{
if
((
stuffp
->
busy
==
0
)
&&
!
stuffp
->
introk
)
WARN
((
"mcdx_transfer() failure in data request
\n
"
));
else
if
(
to
)
WARN
((
"mcdx_transfer(): timeout
\n
"
));
else
if
(
sig
)
WARN
((
"mcdx_transfer(): got signal 0x%lx
\n
"
,
current
->
signal
));
stuffp
->
lock
=
0
;
stuffp
->
busy
=
0
;
wake_up_interruptible
(
&
stuffp
->
lockq
);
...
...
@@ -1365,16 +1479,16 @@ int mcdx_readtoc(struct s_drive_stuff* stuffp)
{
if
(
stuffp
->
toc
)
{
TRACE
((
IOCTL
,
"ioctl() toc already read
\n
"
));
TRACE
((
READTOC
,
"ioctl() toc already read
\n
"
));
return
0
;
}
TRACE
((
IOCTL
,
"ioctl() readtoc for %d tracks
\n
"
,
TRACE
((
READTOC
,
"ioctl() readtoc for %d tracks
\n
"
,
stuffp
->
di
.
n_last
-
stuffp
->
di
.
n_first
+
1
));
if
(
-
1
==
mcdx_hold
(
stuffp
,
1
))
return
-
1
;
TRACE
((
IOCTL
,
"ioctl() tocmode
\n
"
));
TRACE
((
READTOC
,
"ioctl() tocmode
\n
"
));
if
(
-
1
==
mcdx_setdrivemode
(
stuffp
,
TOC
,
1
))
return
-
EIO
;
/* all seems to be ok so far ... malloc */
...
...
@@ -1417,7 +1531,7 @@ int mcdx_readtoc(struct s_drive_stuff* stuffp)
&&
(
q
.
tno
==
0
)
&&
(
stuffp
->
toc
[
idx
-
stuffp
->
di
.
n_first
].
index
==
0
))
{
stuffp
->
toc
[
idx
-
stuffp
->
di
.
n_first
]
=
q
;
TRACE
((
IOCTL
,
"ioctl() toc idx %d (trk %d)
\n
"
,
idx
,
trk
));
TRACE
((
READTOC
,
"ioctl() toc idx %d (trk %d)
\n
"
,
idx
,
trk
));
trk
--
;
}
if
(
trk
==
0
)
break
;
...
...
@@ -1429,16 +1543,16 @@ int mcdx_readtoc(struct s_drive_stuff* stuffp)
}
/* unset toc mode */
TRACE
((
IOCTL
,
"ioctl() undo toc mode
\n
"
));
TRACE
((
READTOC
,
"ioctl() undo toc mode
\n
"
));
if
(
-
1
==
mcdx_setdrivemode
(
stuffp
,
DATA
,
2
))
return
-
EIO
;
#if MCDX_DEBUG &&
IOCTL
#if MCDX_DEBUG &&
READTOC
{
int
trk
;
for
(
trk
=
0
;
trk
<
(
stuffp
->
di
.
n_last
-
stuffp
->
di
.
n_first
+
2
);
trk
++
)
TRACE
((
IOCTL
,
"ioctl() %d readtoc %02x %02x %02x"
TRACE
((
READTOC
,
"ioctl() %d readtoc %02x %02x %02x"
" %02x:%02x.%02x %02x:%02x.%02x
\n
"
,
trk
+
stuffp
->
di
.
n_first
,
stuffp
->
toc
[
trk
].
control
,
stuffp
->
toc
[
trk
].
tno
,
stuffp
->
toc
[
trk
].
index
,
...
...
@@ -1466,14 +1580,14 @@ mcdx_playmsf(struct s_drive_stuff* stuffp, const struct cdrom_msf* msf)
cmd
[
5
]
=
msf
->
cdmsf_sec1
;
cmd
[
6
]
=
msf
->
cdmsf_frame1
;
TRACE
((
IOCTL
,
"ioctl(): play %x "
TRACE
((
PLAYMSF
,
"ioctl(): play %x "
"%02x:%02x:%02x -- %02x:%02x:%02x
\n
"
,
cmd
[
0
],
cmd
[
1
],
cmd
[
2
],
cmd
[
3
],
cmd
[
4
],
cmd
[
5
],
cmd
[
6
]));
outsb
((
unsigned
int
)
stuffp
->
wreg_data
,
cmd
,
sizeof
cmd
);
if
(
-
1
==
mcdx_getval
(
stuffp
,
1
*
HZ
,
0
,
NULL
))
{
if
(
-
1
==
mcdx_getval
(
stuffp
,
3
*
HZ
,
0
,
NULL
))
{
WARN
((
"playmsf() timeout
\n
"
));
return
-
1
;
}
...
...
@@ -1516,26 +1630,26 @@ static int
mcdx_closedoor
(
struct
s_drive_stuff
*
stuffp
,
int
tries
)
{
if
(
stuffp
->
present
&
DOOR
)
return
mcdx_talk
(
stuffp
,
"
\xf8
"
,
1
,
NULL
,
0
,
5
*
HZ
,
tries
);
return
mcdx_talk
(
stuffp
,
"
\xf8
"
,
1
,
NULL
,
1
,
5
*
HZ
,
tries
);
else
return
0
;
}
static
int
mcdx_stop
(
struct
s_drive_stuff
*
stuffp
,
int
tries
)
{
return
mcdx_talk
(
stuffp
,
"
\xf0
"
,
1
,
NULL
,
0
,
2
*
HZ
,
tries
);
}
{
return
mcdx_talk
(
stuffp
,
"
\xf0
"
,
1
,
NULL
,
1
,
2
*
HZ
,
tries
);
}
static
int
mcdx_hold
(
struct
s_drive_stuff
*
stuffp
,
int
tries
)
{
return
mcdx_talk
(
stuffp
,
"
\x70
"
,
1
,
NULL
,
0
,
2
*
HZ
,
tries
);
}
{
return
mcdx_talk
(
stuffp
,
"
\x70
"
,
1
,
NULL
,
1
,
2
*
HZ
,
tries
);
}
static
int
mcdx_eject
(
struct
s_drive_stuff
*
stuffp
,
int
tries
)
{
if
(
stuffp
->
present
&
DOOR
)
return
mcdx_talk
(
stuffp
,
"
\xf6
"
,
1
,
NULL
,
0
,
5
*
HZ
,
tries
)
;
else
return
0
;
if
(
stuffp
->
present
&
DOOR
)
{
stuffp
->
ejected
=
jiffies
;
return
mcdx_talk
(
stuffp
,
"
\xf6
"
,
1
,
NULL
,
1
,
5
*
HZ
,
tries
);
}
else
return
0
;
}
static
int
...
...
@@ -1618,7 +1732,7 @@ mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode, int tries)
default:
break
;
}
cmd
[
0
]
=
0x50
;
return
mcdx_talk
(
stuffp
,
cmd
,
2
,
NULL
,
0
,
5
*
HZ
,
tries
);
return
mcdx_talk
(
stuffp
,
cmd
,
2
,
NULL
,
1
,
5
*
HZ
,
tries
);
}
...
...
@@ -1633,7 +1747,7 @@ mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode, int tries)
case
MODE2
:
cmd
[
1
]
=
0x02
;
break
;
default:
return
-
EINVAL
;
}
return
mcdx_talk
(
stuffp
,
cmd
,
2
,
NULL
,
0
,
5
*
HZ
,
tries
);
return
mcdx_talk
(
stuffp
,
cmd
,
2
,
NULL
,
1
,
5
*
HZ
,
tries
);
}
static
int
...
...
@@ -1648,13 +1762,13 @@ mcdx_config(struct s_drive_stuff *stuffp, int tries)
cmd
[
1
]
=
0x10
;
/* irq enable */
cmd
[
2
]
=
0x05
;
/* pre, err irq enable */
if
(
-
1
==
mcdx_talk
(
stuffp
,
cmd
,
3
,
NULL
,
0
,
1
*
HZ
,
tries
))
if
(
-
1
==
mcdx_talk
(
stuffp
,
cmd
,
3
,
NULL
,
1
,
1
*
HZ
,
tries
))
return
-
1
;
cmd
[
1
]
=
0x02
;
/* dma select */
cmd
[
2
]
=
0x00
;
/* no dma */
return
mcdx_talk
(
stuffp
,
cmd
,
3
,
NULL
,
0
,
1
*
HZ
,
tries
);
return
mcdx_talk
(
stuffp
,
cmd
,
3
,
NULL
,
1
,
1
*
HZ
,
tries
);
}
static
int
...
...
@@ -1679,7 +1793,7 @@ mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries)
outb
(
0
,
(
unsigned
int
)
stuffp
->
wreg_chn
);
/* no dma, no irq -> hardware */
outb
(
0
,
(
unsigned
int
)
stuffp
->
wreg_reset
);
/* hw reset */
return
0
;
}
else
return
mcdx_talk
(
stuffp
,
"
\x60
"
,
1
,
NULL
,
0
,
5
*
HZ
,
tries
);
}
else
return
mcdx_talk
(
stuffp
,
"
\x60
"
,
1
,
NULL
,
1
,
5
*
HZ
,
tries
);
}
static
int
...
...
@@ -1688,14 +1802,14 @@ mcdx_lockdoor(struct s_drive_stuff *stuffp, int lock, int tries)
char
cmd
[
2
]
=
{
0xfe
};
if
(
stuffp
->
present
&
DOOR
)
{
cmd
[
1
]
=
lock
?
0x01
:
0x00
;
return
mcdx_talk
(
stuffp
,
cmd
,
sizeof
(
cmd
),
NULL
,
0
,
5
*
HZ
,
tries
);
return
mcdx_talk
(
stuffp
,
cmd
,
sizeof
(
cmd
),
NULL
,
1
,
5
*
HZ
,
tries
);
}
else
return
0
;
}
static
int
mcdx_getstatus
(
struct
s_drive_stuff
*
stuffp
,
int
tries
)
{
return
mcdx_talk
(
stuffp
,
"
\x40
"
,
1
,
NULL
,
0
,
5
*
HZ
,
tries
);
}
{
return
mcdx_talk
(
stuffp
,
"
\x40
"
,
1
,
NULL
,
1
,
5
*
HZ
,
tries
);
}
static
int
mcdx_getval
(
struct
s_drive_stuff
*
stuffp
,
int
to
,
int
delay
,
char
*
buf
)
...
...
@@ -1714,3 +1828,20 @@ mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char* buf)
return
0
;
}
static
int
mcdx_setattentuator
(
struct
s_drive_stuff
*
stuffp
,
struct
cdrom_volctrl
*
vol
,
int
tries
)
{
char
cmd
[
5
];
cmd
[
0
]
=
0xae
;
cmd
[
1
]
=
vol
->
channel0
;
cmd
[
2
]
=
0
;
cmd
[
3
]
=
vol
->
channel1
;
cmd
[
4
]
=
0
;
return
mcdx_talk
(
stuffp
,
cmd
,
sizeof
(
cmd
),
NULL
,
5
,
200
,
tries
);
}
drivers/char/Config.in
View file @
a89a2558
...
...
@@ -4,7 +4,7 @@
mainmenu_option next_comment
comment 'character devices'
bool
'Cyclades async mux support' CONFIG_CYCLADES
tristate
'Cyclades async mux support' CONFIG_CYCLADES
bool 'Stallion multiport serial support' CONFIG_STALDRV
if [ "$CONFIG_STALDRV" = "y" ]; then
tristate ' Stallion EasyIO or EC8/32 support' CONFIG_STALLION
...
...
drivers/char/Makefile
View file @
a89a2558
...
...
@@ -20,8 +20,12 @@ L_OBJS := tty_io.o n_tty.o console.o keyboard.o serial.o \
tty_ioctl.o pty.o vt.o mem.o vc_screen.o random.o
\
defkeymap.o consolemap.o selection.o
if
def
CONFIG_CYCLADES
if
eq
($(CONFIG_CYCLADES),y)
L_OBJS
+=
cyclades.o
else
ifeq
($(CONFIG_CYCLADES),m)
M_OBJS
+=
cyclades.o
endif
endif
ifeq
($(CONFIG_STALLION),y)
...
...
drivers/char/cyclades.c
View file @
a89a2558
...
...
@@ -223,6 +223,8 @@ static char rcsid[] =
*
*/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/signal.h>
#include <linux/sched.h>
...
...
@@ -404,7 +406,6 @@ static int startup (struct cyclades_port *);
static
void
cy_throttle
(
struct
tty_struct
*
);
static
void
cy_unthrottle
(
struct
tty_struct
*
);
static
void
config_setup
(
struct
cyclades_port
*
);
extern
void
console_print
(
const
char
*
);
#ifdef CYCLOM_SHOW_STATUS
static
void
show_status
(
int
);
#endif
...
...
@@ -466,7 +467,6 @@ void CP2(int data) { CP1((data>>4) & 0x0f); CP1( data & 0x0f); }/* CP2 */
void
CP4
(
int
data
)
{
CP2
((
data
>>
8
)
&
0xff
);
CP2
(
data
&
0xff
);
}
/* CP4 */
void
CP8
(
long
data
)
{
CP4
((
data
>>
16
)
&
0xffff
);
CP4
(
data
&
0xffff
);
}
/* CP8 */
/* This routine waits up to 1000 micro-seconds for the previous
command to the Cirrus chip to complete and then issues the
new command. An error is returned if the previous command
...
...
@@ -583,6 +583,7 @@ cy_sched_event(struct cyclades_port *info, int event)
}
/* cy_sched_event */
static
int
probe_ready
;
/*
* This interrupt routine is used
...
...
@@ -594,6 +595,9 @@ cy_probe(int irq, struct pt_regs *regs)
int
save_xir
,
save_car
;
int
index
=
0
;
/* probing interrupts is only for ISA */
if
(
!
probe_ready
)
return
;
cy_irq_triggered
=
irq
;
cy_triggered
|=
1
<<
irq
;
...
...
@@ -1107,6 +1111,7 @@ get_auto_irq(unsigned char *address)
base_addr
[
CyCAR
<<
index
]
=
0
;
write_cy_cmd
(
base_addr
,
CyCHAN_CTL
|
CyENB_XMTR
,
index
);
base_addr
[
CySRER
<<
index
]
|=
CyTxMpty
;
probe_ready
=
1
;
sti
();
timeout
=
jiffies
+
2
;
...
...
@@ -1114,6 +1119,7 @@ get_auto_irq(unsigned char *address)
if
(
cy_irq_triggered
)
break
;
}
probe_ready
=
0
;
return
(
cy_irq_triggered
);
}
/* get_auto_irq */
...
...
@@ -1132,6 +1138,8 @@ do_auto_irq(unsigned char *address)
/* Turn on interrupts (they may be off) */
save_flags
(
flags
);
sti
();
probe_ready
=
0
;
cy_wild_int_mask
=
check_wild_interrupts
();
irq_lines
=
grab_all_interrupts
(
cy_wild_int_mask
);
...
...
@@ -2286,6 +2294,7 @@ static void
cy_close
(
struct
tty_struct
*
tty
,
struct
file
*
filp
)
{
struct
cyclades_port
*
info
=
(
struct
cyclades_port
*
)
tty
->
driver_data
;
unsigned
long
flags
;
/* CP('C'); */
#ifdef SERIAL_DEBUG_OTHER
...
...
@@ -2300,6 +2309,14 @@ cy_close(struct tty_struct * tty, struct file * filp)
printk
(
"cy_close ttyC%d, count = %d
\n
"
,
info
->
line
,
info
->
count
);
#endif
save_flags
(
flags
);
cli
();
/* If the TTY is being hung up, nothing to do */
if
(
tty_hung_up_p
(
filp
))
{
restore_flags
(
flags
);
return
;
}
if
((
tty
->
count
==
1
)
&&
(
info
->
count
!=
1
))
{
/*
* Uh, oh. tty->count is 1, which means that the tty
...
...
@@ -2313,7 +2330,7 @@ cy_close(struct tty_struct * tty, struct file * filp)
info
->
count
=
1
;
}
#ifdef SERIAL_DEBUG_COUNT
printk
(
"cyc: %d
: decrementing count to %d
\n
"
,
__LINE__
,
info
->
count
-
1
);
printk
(
"cyc: %d
(%d): decrementing count to %d
\n
"
,
__LINE__
,
current
->
pid
,
info
->
count
-
1
);
#endif
if
(
--
info
->
count
<
0
)
{
#ifdef SERIAL_DEBUG_COUNT
...
...
@@ -2322,7 +2339,11 @@ cy_close(struct tty_struct * tty, struct file * filp)
info
->
count
=
0
;
}
if
(
info
->
count
)
{
MOD_DEC_USE_COUNT
;
restore_flags
(
flags
);
return
;
}
info
->
flags
|=
ASYNC_CLOSING
;
/*
* Save the termios structure, since this port may have
...
...
@@ -2341,14 +2362,6 @@ cy_close(struct tty_struct * tty, struct file * filp)
tty
->
ldisc
.
flush_buffer
(
tty
);
info
->
event
=
0
;
info
->
tty
=
0
;
if
(
tty
->
ldisc
.
num
!=
ldiscs
[
N_TTY
].
num
)
{
if
(
tty
->
ldisc
.
close
)
(
tty
->
ldisc
.
close
)(
tty
);
tty
->
ldisc
=
ldiscs
[
N_TTY
];
tty
->
termios
->
c_line
=
N_TTY
;
if
(
tty
->
ldisc
.
open
)
(
tty
->
ldisc
.
open
)(
tty
);
}
if
(
info
->
blocked_open
)
{
if
(
info
->
close_delay
)
{
current
->
state
=
TASK_INTERRUPTIBLE
;
...
...
@@ -2365,6 +2378,8 @@ cy_close(struct tty_struct * tty, struct file * filp)
printk
(
"cy_close done
\n
"
);
#endif
MOD_DEC_USE_COUNT
;
restore_flags
(
flags
);
return
;
}
/* cy_close */
...
...
@@ -2384,14 +2399,12 @@ cy_hangup(struct tty_struct *tty)
return
;
shutdown
(
info
);
#if 0
info
->
event
=
0
;
info
->
count
=
0
;
#ifdef SERIAL_DEBUG_COUNT
printk("cyc: %d
: setting count to 0\n", __LINE__
);
printk
(
"cyc: %d
(%d): setting count to 0
\n
"
,
__LINE__
,
current
->
pid
);
#endif
info
->
tty
=
0
;
#endif
info
->
flags
&=
~
(
ASYNC_NORMAL_ACTIVE
|
ASYNC_CALLOUT_ACTIVE
);
wake_up_interruptible
(
&
info
->
open_wait
);
}
/* cy_hangup */
...
...
@@ -2477,7 +2490,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
#endif
info
->
count
--
;
#ifdef SERIAL_DEBUG_COUNT
printk
(
"cyc: %d
: decrementing count to %d
\n
"
,
__LINE__
,
info
->
count
);
printk
(
"cyc: %d
(%d): decrementing count to %d
\n
"
,
__LINE__
,
current
->
pid
,
info
->
count
);
#endif
info
->
blocked_open
++
;
...
...
@@ -2537,7 +2550,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
if
(
!
tty_hung_up_p
(
filp
)){
info
->
count
++
;
#ifdef SERIAL_DEBUG_COUNT
printk
(
"cyc: %d
: incrementing count to %d
\n
"
,
__LINE__
,
info
->
count
);
printk
(
"cyc: %d
(%d): incrementing count to %d
\n
"
,
__LINE__
,
current
->
pid
,
info
->
count
);
#endif
}
info
->
blocked_open
--
;
...
...
@@ -2581,7 +2594,7 @@ cy_open(struct tty_struct *tty, struct file * filp)
#endif
info
->
count
++
;
#ifdef SERIAL_DEBUG_COUNT
printk
(
"cyc: %d
: incrementing count to %d
\n
"
,
__LINE__
,
info
->
count
);
printk
(
"cyc: %d
(%d): incrementing count to %d
\n
"
,
__LINE__
,
current
->
pid
,
info
->
count
);
#endif
tty
->
driver_data
=
info
;
info
->
tty
=
tty
;
...
...
@@ -2622,6 +2635,7 @@ cy_open(struct tty_struct *tty, struct file * filp)
#ifdef SERIAL_DEBUG_OPEN
printk
(
"cy_open done
\n
"
);
/**/
#endif
MOD_INC_USE_COUNT
;
return
0
;
}
/* cy_open */
...
...
@@ -2736,7 +2750,6 @@ cy_init(void)
struct
cyclades_card
*
cinfo
;
int
board
,
port
,
i
;
scrn
[
1
]
=
'\0'
;
show_version
();
/* Initialize the tty_driver structure */
...
...
@@ -2877,6 +2890,33 @@ scrn[1] = '\0';
}
/* cy_init */
#ifdef MODULE
int
init_module
(
void
)
{
return
(
cy_init
());
}
void
cleanup_module
(
void
)
{
int
i
;
if
(
tty_unregister_driver
(
&
cy_callout_driver
))
printk
(
"Couldn't unregister Cyclom callout driver
\n
"
);
if
(
tty_unregister_driver
(
&
cy_serial_driver
))
printk
(
"Couldn't unregister Cyclom serial driver
\n
"
);
for
(
i
=
0
;
i
<
NR_CARDS
;
i
++
)
{
if
(
cy_card
[
i
].
base_addr
!=
0
)
{
free_irq
(
cy_card
[
i
].
irq
);
}
}
}
#endif
/*
* ---------------------------------------------------------------------
* cy_detect_isa() - Probe for Cyclom-Y/ISA boards.
...
...
drivers/net/3c505.c
View file @
a89a2558
...
...
@@ -10,7 +10,7 @@
* be here without 3C505 technical reference provided by
* 3Com.
*
* Version: @(#)3c505.c 0.8.
1 26-Jun
-95
* Version: @(#)3c505.c 0.8.
3 12-Nov
-95
*
* Authors: Linux 3c505 device driver by
* Craig Southeren, <craigs@ineluki.apana.org.au>
...
...
@@ -103,7 +103,7 @@ static int elp_debug = 0;
* 3 = messages when interrupts received
*/
#define ELP_VERSION "0.8.
1
"
#define ELP_VERSION "0.8.
3
"
/*****************************************************************
*
...
...
@@ -473,9 +473,13 @@ static void
adapter_hard_reset
(
struct
device
*
dev
)
{
int
timeout
;
long
flags
;
CHECK_NULL
(
dev
);
save_flags
(
flags
);
sti
();
if
(
elp_debug
>
0
)
printk
(
"%s: Resetting the adapter, please wait (approx 20 s)
\n
"
,
dev
->
name
);
...
...
@@ -507,6 +511,7 @@ adapter_hard_reset (struct device * dev)
for
(
timeout
=
jiffies
+
(
100
*
15
);
jiffies
<=
timeout
;
)
if
(
GET_ASF
(
dev
->
base_addr
)
!=
ASF_PCB_END
)
break
;
restore_flags
(
flags
);
}
/******************************************************
...
...
@@ -1272,6 +1277,7 @@ elp_sense (struct device * dev)
int
timeout
;
int
addr
=
dev
->
base_addr
;
const
char
*
name
=
dev
->
name
;
long
flags
;
byte
orig_HCR
=
inb_control
(
addr
),
orig_HSR
=
inb_status
(
addr
);
...
...
@@ -1286,6 +1292,10 @@ elp_sense (struct device * dev)
return
-
1
;
/* It can't be 3c505 if HCR.DIR != HSR.DIR */
}
/* Enable interrupts - we need timers! */
save_flags
(
flags
);
sti
();
/* Wait for a while; the adapter may still be booting up */
if
(
elp_debug
>
0
)
printk
(
stilllooking_msg
);
...
...
@@ -1299,6 +1309,7 @@ elp_sense (struct device * dev)
timeout
=
jiffies
+
30
;
while
(
jiffies
<
timeout
)
;
restore_flags
(
flags
);
if
(
inb_status
(
addr
)
&
DIR
)
{
outb_control
(
orig_HCR
,
addr
);
if
(
elp_debug
>
0
)
...
...
@@ -1311,6 +1322,7 @@ elp_sense (struct device * dev)
timeout
=
jiffies
+
300
;
while
(
jiffies
<
timeout
)
;
restore_flags
(
flags
);
if
(
!
(
inb_status
(
addr
)
&
DIR
))
{
outb_control
(
orig_HCR
,
addr
);
if
(
elp_debug
>
0
)
...
...
@@ -1462,8 +1474,8 @@ static struct device dev_3c505 = {
0
,
0
,
0
,
0
,
0
,
NULL
,
elplus_probe
};
static
int
io
=
0x300
;
static
int
irq
=
0
;
int
io
=
0x300
;
int
irq
=
0
;
int
init_module
(
void
)
{
...
...
drivers/net/arcnet.c
View file @
a89a2558
/* arcnet.c
Written 1994-95 by Avery Pennarun, derived from skeleton.c by
Donald
Becker.
Written 1994-95 by Avery Pennarun, derived from skeleton.c by
Donald
Becker.
Contact Avery at: apenwarr@foxnet.net or
RR #5 Pole Line Road, Thunder Bay, ON, Canada P7C 5M9
...
...
@@ -17,6 +17,38 @@
**********************
v2.20 ALPHA (95/11/12)
- Added a bit of protocol confusion to the arc0 code to allow
trxnet-compatible IPX support - and the use of all that new
Linux-IPX stuff (including lwared). Just tell the ipx_interface
command that arc0 uses 802.3 (other protocols will probably also
work).
- Fixed lp->stats to update tx_packets on all devices, not just
arc0. Also, changed a lot of the error counting to make more
sense.
- rx_packets on arc0 was being updated for each completely received
packet. It now updates for each segment received, which makes
more sense.
- Removed unneeded extra check of dev->start in arcnet_inthandler.
- Included someone else's fixes from kernel 1.3.39. Does it still
work with kernel 1.2?
- Added a new define to disable PRINTING (not checking) of RECON
messages.
- Separated the duplicated error checking code from the various
arcnet??_send_packet routines into a new function.
- Cleaned up lock variables and ping-pong buffers a bit. This
should mean more stability, fewer missing packets, and less ugly
debug messages. Assuming it works.
- Changed the format of debug messages to always include the actual
device name instead of just "arcnet:". Used more macros to
shorten debugging code even more.
- Finally squashed the "startup NULL pointer" bug. irq2dev_map
wasn't being cleared to NULL when the driver was closed.
- Improved RECON checking; if a certain number of RECON messages
are received within one minute, a warning message is printed
to the effect of "cabling problem." One-log-message-per-recon
now defaults to OFF.
v2.12 ALPHA (95/10/27)
- Tried to improve skb handling and init code to fix problems with
the latest 1.3.x kernels. (We no longer use ether_setup except
...
...
@@ -94,13 +126,14 @@
if there aren't any ARCnet cards in the system. And why shouldn't
it work as a module again?
- Rewrite autoprobe.
- Make sure RESET flag is cleared during an IRQ even if dev->start==0;
mainly a portability fix. This will confuse autoprobe a bit, so
test that too.
- What about cards with shared memory that can be "turned off?"
- NFS mount freezes after several megabytes to SOSS for DOS.
unmount/remount fixes it. Is this arcnet-specific? I don't know.
- Some newer ARCnets support promiscuous mode, supposedly.
If someone sends me information, I'll try to implement it.
- Find and remove excess lock variables that are probably not
necessary anymore due to the changes in Linux 1.2.9.
- Some newer ARCnets support promiscuous mode, supposedly. If
someone sends me information, I'll try to implement it.
- Dump Linux 1.2 support and its ugly #ifdefs.
- Add support for the new 1.3.x IP header cache features.
- ATA protocol support??
...
...
@@ -123,11 +156,14 @@
*/
static
const
char
*
version
=
"arcnet.c:
v2.12 ALPHA 95/10/27
Avery Pennarun <apenwarr@foxnet.net>
\n
"
;
"arcnet.c:
v2.20 ALPHA 95/11/12
Avery Pennarun <apenwarr@foxnet.net>
\n
"
;
#include <linux/module.h>
#include <linux/module.h>
#include <linux/config.h>
#include <linux/version.h>
/* are we Linux 1.2.x? */
#if LINUX_VERSION_CODE < 0x10300
#define LINUX12
...
...
@@ -152,7 +188,7 @@ static const char *version =
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/config.h>
/* f
or CONFIG_INET */
/*#include <linux/config.h>*/
/* F
or CONFIG_INET */
#include <asm/system.h>
#include <asm/bitops.h>
...
...
@@ -167,18 +203,34 @@ static const char *version =
/**************************************************************************/
/* Define this if you want to detect network reconfigurations.
* They may be a real nuisance on a larger ARCnet network: but if you are
* a network administrator you probably would like to count them.
* Reconfigurations will be recorded in stats.tx_carrier_errors
* (the last field of the /proc/net/dev file).
*
* The card sends the reconfiguration signal when it loses the connection
* to the rest of its network. It is a 'Hello, is anybody there?' cry. This
/* The card sends the reconfiguration signal when it loses the connection to
* the rest of its network. It is a 'Hello, is anybody there?' cry. This
* usually happens when a new computer on the network is powered on or when
* the cable is broken.
*
* Define DETECT_RECONFIGS if you want to detect network reconfigurations.
* They may be a real nuisance on a larger ARCnet network; if you are a
* network administrator you probably would like to count them.
* Reconfigurations will be recorded in stats.tx_carrier_errors (the last
* field of the /proc/net/dev file).
*
* Define SHOW_RECONFIGS if you really want to see a log message whenever
* a RECON occurs.
*/
#define DETECT_RECONFIGS
#undef SHOW_RECONFIGS
/* RECON_THRESHOLD is the maximum number of RECON messages to receive within
* one minute before printing a "cabling problem" warning. You must have
* DETECT_RECONFIGS enabled if you want to use this. The default value
* should be fine.
*
* After that, a "cabling restored" message will be printed on the next IRQ
* if no RECON messages have been received for 10 seconds.
*
* Do not define RECON_THRESHOLD at all if you want to disable this feature.
*/
#define RECON_THRESHOLD 30
/* Define this if you want to make sure transmitted packets are "acknowledged"
* by the destination host, as long as they're not to the broadcast address.
...
...
@@ -190,26 +242,33 @@ static const char *version =
*/
#define VERIFY_ACK
/* Define this to the minimum "timeout" value. If a transmit takes longer
* than TX_TIMEOUT jiffies, Linux will abort the TX and retry. On a large
* network, or one with heavy network traffic, this timeout may need to be
* increased.
*/
#define TX_TIMEOUT 20
/* Define this if you want to make it easier to use the "call trace" when
* a kernel NULL pointer assignment occurs. Hopefully unnecessary, most of
* the time. It will make all the function names (and other things) show
* up as kernel symbols. (especially handy when using arcnet as a module)
*/
#
define
static
#
undef
static
/**************************************************************************/
/*
n
ew debugging bitflags: each option can be enabled individually.
/*
N
ew debugging bitflags: each option can be enabled individually.
*
*
t
hese can be set while the driver is running by typing:
*
T
hese can be set while the driver is running by typing:
* ifconfig arc0 down metric 1xxx HOSTNAME
* where 1xxx is 1000 + the debug level you want
* and HOSTNAME is your hostname/ip address
* and then resetting your routes.
*
* Note: only debug flags included in the ARCNET_DEBUG_MAX define will
* actually be available. GCC
(at least 2.7.0) will notice lines
* using a BUGLVL not in ARCNET_DEBUG_MAX and automatically optimize
* actually be available. GCC
will (at least, GCC 2.7.0 will) notice
*
lines
using a BUGLVL not in ARCNET_DEBUG_MAX and automatically optimize
* them out.
*/
#define D_NORMAL 1
/* D_NORMAL normal operational info */
...
...
@@ -233,8 +292,9 @@ static const char *version =
#endif
int
arcnet_debug
=
ARCNET_DEBUG
;
/* macro to simplify debug checking */
/* macro
s
to simplify debug checking */
#define BUGLVL(x) if ((ARCNET_DEBUG_MAX)&arcnet_debug&(x))
#define BUGMSG(x,msg,args...) BUGLVL(x) printk("%6s: " msg, dev->name , ## args);
#ifndef HAVE_AUTOIRQ
/* From auto_irq.c, in ioport.h for later versions. */
...
...
@@ -257,12 +317,14 @@ extern struct device *irq2dev_map[16];
#define IF_TBUSY (lp->adev->tbusy \
|| lp->edev->tbusy \
|| lp->sdev->tbusy)
#define INTERRUPT lp->adev->interrupt \
=lp->edev->interrupt \
=lp->sdev->interrupt
#define IF_INTERRUPT (lp->adev->interrupt \
|| lp->edev->interrupt \
|| lp->sdev->interrupt)
#define START lp->adev->start \
=lp->edev->start \
=lp->sdev->start
...
...
@@ -343,7 +405,7 @@ extern struct device *irq2dev_map[16];
#define NORMALconf 0x00
/* 1-249 byte packets */
#define EXTconf 0x08
/* 250-504 byte packets */
/*
buffers (4 total) used for receive and xmit
.
/*
Starts receiving packets into recbuf
.
*/
#define EnableReceiver() outb(RXcmd|(recbuf<<3)|RXbcasts,COMMAND)
...
...
@@ -361,7 +423,7 @@ extern struct device *irq2dev_map[16];
#define ARC_P_ETHER 0xE8
/* Unsupported/indirectly supported protocols */
#define ARC_P_LANSOFT 251
/* 0xFB */
#define ARC_P_LANSOFT 251
/* 0xFB
- what is this?
*/
#define ARC_P_ATALK 0xDD
/* the header required by the card itself */
...
...
@@ -461,6 +523,13 @@ struct arcnet_local {
sending
;
/* transmit in progress? */
short
tx_left
;
/* segments of split packet left to TX */
#if defined(DETECT_RECONFIGS) && defined(RECON_THRESHOLD)
time_t
first_recon
,
/* time of "first" RECON message to count */
last_recon
;
/* time of most recent RECON */
int
num_recons
,
/* number of RECONs between first and last. */
network_down
;
/* do we think the network is down? */
#endif
struct
timer_list
timer
;
/* the timer interrupt struct */
struct
Incoming
incoming
[
256
];
/* one from each address */
struct
Outgoing
outgoing
;
/* packet currently being sent */
...
...
@@ -485,13 +554,14 @@ static int arcnet_open(struct device *dev);
static
int
arcnet_close
(
struct
device
*
dev
);
static
int
arcnet_reset
(
struct
device
*
dev
);
static
int
arcnet_send_packet_bad
(
struct
sk_buff
*
skb
,
struct
device
*
dev
);
static
int
arcnetA_send_packet
(
struct
sk_buff
*
skb
,
struct
device
*
dev
);
static
int
arcnetE_send_packet
(
struct
sk_buff
*
skb
,
struct
device
*
dev
);
static
int
arcnetS_send_packet
(
struct
sk_buff
*
skb
,
struct
device
*
dev
);
static
void
arcnetA_continue_tx
(
struct
device
*
dev
);
static
void
arcnetAS_prepare_tx
(
struct
device
*
dev
,
u_char
*
hdr
,
int
hdrlen
,
char
*
data
,
int
length
,
int
daddr
,
int
exceptA
);
static
void
arcnetAS_go_tx
(
struct
device
*
dev
);
static
int
arcnet_go_tx
(
struct
device
*
dev
,
int
enable_irq
);
static
void
arcnet_interrupt
(
int
irq
,
struct
pt_regs
*
regs
);
static
void
arcnet_inthandler
(
struct
device
*
dev
);
...
...
@@ -608,8 +678,7 @@ arcnet_probe(struct device *dev)
}
#endif
BUGLVL
(
D_INIT
)
printk
(
"arcnet: given: base %lXh, IRQ %Xh, shmem %lXh
\n
"
,
BUGMSG
(
D_INIT
,
"given: base %lXh, IRQ %Xh, shmem %lXh
\n
"
,
dev
->
base_addr
,
dev
->
irq
,
dev
->
mem_start
);
#ifndef MODULE
...
...
@@ -622,8 +691,7 @@ arcnet_probe(struct device *dev)
int
ioaddr
=
*
port
;
if
(
check_region
(
ioaddr
,
ARCNET_TOTAL_SIZE
))
{
BUGLVL
(
D_INIT
)
printk
(
"arcnet: Skipping %Xh because of check_region...
\n
"
,
BUGMSG
(
D_INIT
,
"Skipping %Xh because of check_region...
\n
"
,
ioaddr
);
continue
;
}
...
...
@@ -637,13 +705,11 @@ arcnet_probe(struct device *dev)
/* ioprobe turned out okay. Now give it a couple seconds to finish
* initializing...
*/
BUGLVL
(
D_INIT
)
printk
(
"arcnet: ioprobe okay! Waiting for reset...
\n
"
);
BUGMSG
(
D_INIT
,
"ioprobe okay! Waiting for reset...
\n
"
);
JIFFER
(
100
);
/* okay, now we have to find the shared memory area. */
BUGLVL
(
D_INIT
)
printk
(
"arcnet: starting memory probe, given %lXh
\n
"
,
BUGMSG
(
D_INIT
,
"starting memory probe, given %lXh
\n
"
,
dev
->
mem_start
);
if
(
dev
->
mem_start
)
/* value given - probe just that one */
{
...
...
@@ -663,9 +729,11 @@ arcnet_probe(struct device *dev)
if
(
!
dev
->
base_addr
||
!
dev
->
irq
||
!
dev
->
mem_start
||
!
dev
->
rmem_start
)
{
printk
(
"arcnet: loadable modules can't autoprobe!
\n
"
);
printk
(
"arcnet: try using io=, irqnum=, and shmem= on the insmod line.
\n
"
);
printk
(
"arcnet: you may also need num= to change the device name. (ie. num=1 for arc1)
\n
"
);
printk
(
"%6s: loadable modules can't autoprobe!
\n
"
,
dev
->
name
);
printk
(
"%6s: try using io=, irqnum=, and shmem= on the insmod line.
\n
"
,
dev
->
name
);
printk
(
"%6s: you may also need num= to change the device name. (ie. num=1 for arc1)
\n
"
,
dev
->
name
);
return
ENODEV
;
}
#endif
...
...
@@ -674,7 +742,7 @@ arcnet_probe(struct device *dev)
int
irqval
=
request_irq
(
dev
->
irq
,
&
arcnet_interrupt
,
0
,
"arcnet"
);
if
(
irqval
)
{
printk
(
"%s: unable to get IRQ %d (irqval=%d).
\n
"
,
printk
(
"%
6
s: unable to get IRQ %d (irqval=%d).
\n
"
,
dev
->
name
,
dev
->
irq
,
irqval
);
return
EAGAIN
;
}
...
...
@@ -683,7 +751,7 @@ arcnet_probe(struct device *dev)
/* Grab the region so we can find another board if autoIRQ fails. */
request_region
(
dev
->
base_addr
,
ARCNET_TOTAL_SIZE
,
"arcnet"
);
printk
(
"%s: ARCnet card found at %03lXh, IRQ %d, ShMem at %lXh.
\n
"
,
printk
(
"%
6
s: ARCnet card found at %03lXh, IRQ %d, ShMem at %lXh.
\n
"
,
dev
->
name
,
dev
->
base_addr
,
dev
->
irq
,
dev
->
mem_start
);
/* Initialize the device structure. */
...
...
@@ -709,24 +777,26 @@ arcnet_probe(struct device *dev)
/* And now fill particular fields with arcnet values */
dev
->
mtu
=
1500
;
/* completely arbitrary - agrees with ether, though */
dev
->
hard_header_len
=
sizeof
(
struct
ClientData
);
BUGLVL
(
D_DURING
)
printk
(
"arcnet: ClientData header size is %d.
\n
arcnet: HardHeader size is %d.
\n
"
,
sizeof
(
struct
ClientData
),
sizeof
(
struct
HardHeader
));
BUGMSG
(
D_DURING
,
"ClientData header size is %d.
\n
"
,
sizeof
(
struct
ClientData
));
BUGMSG
(
D_DURING
,
"HardHeader size is %d.
\n
"
,
sizeof
(
struct
HardHeader
));
/* since we strip EXTRA_CLIENTDATA bytes off before sending,
* we let Linux add that many bytes to the packet data...
*/
BUG
LVL
(
D_INIT
)
printk
(
"arcnet:
arcnet_probe: resetting card.
\n
"
);
BUG
MSG
(
D_INIT
,
"
arcnet_probe: resetting card.
\n
"
);
arcnet_reset
(
dev
);
JIFFER
(
50
);
BUGLVL
(
D_NORMAL
)
printk
(
"arcnet: We appear to be station %d (%02Xh)
\n
"
,
BUGMSG
(
D_NORMAL
,
"We appear to be station %d (%02Xh)
\n
"
,
lp
->
arcnum
,
lp
->
arcnum
);
if
(
lp
->
arcnum
==
0
)
printk
(
"arcnet: WARNING! Station address 0 is reserved for broadcasts!
\n
"
);
printk
(
"%6s: WARNING! Station address 0 is reserved for broadcasts!
\n
"
,
dev
->
name
);
if
(
lp
->
arcnum
==
255
)
printk
(
"arcnet: WARNING! Station address 255 may confuse DOS networking programs!
\n
"
);
printk
(
"%6s: WARNING! Station address 255 may confuse DOS networking programs!
\n
"
,
dev
->
name
);
dev
->
dev_addr
[
0
]
=
lp
->
arcnum
;
lp
->
sequence
=
1
;
lp
->
recbuf
=
0
;
...
...
@@ -747,11 +817,8 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
{
int
delayval
,
airq
;
BUGLVL
(
D_INIT
)
{
printk
(
"arcnet: probing address %Xh
\n
"
,
ioaddr
);
printk
(
"arcnet: status1=%Xh
\n
"
,
inb
(
STATUS
));
}
BUGMSG
(
D_INIT
,
"probing address %Xh
\n
"
,
ioaddr
);
BUGMSG
(
D_INIT
,
" status1=%Xh
\n
"
,
inb
(
STATUS
));
/* very simple - all we have to do is reset the card, and if there's
...
...
@@ -766,8 +833,7 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
/* if status port is FF, there's certainly no arcnet... give up. */
if
(
inb
(
STATUS
)
==
0xFF
)
{
BUGLVL
(
D_INIT
)
printk
(
"arcnet: probe failed. Status port empty.
\n
"
);
BUGMSG
(
D_INIT
,
" probe failed. Status port empty.
\n
"
);
return
ENODEV
;
}
...
...
@@ -787,22 +853,20 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
if (curval==initval)
{
printk("arcnet:
probe failed. never-changing command port (%02Xh).\n",
BUGLVL(D_INIT,"
probe failed. never-changing command port (%02Xh).\n",
initval);
return ENODEV;
}
}
#endif
BUGLVL
(
D_INIT
)
printk
(
"arcnet: status2=%Xh
\n
"
,
inb
(
STATUS
));
BUGMSG
(
D_INIT
,
" status2=%Xh
\n
"
,
inb
(
STATUS
));
/* now we turn the reset bit off so we can IRQ next reset... */
outb
(
CFLAGScmd
|
RESETclear
|
CONFIGclear
,
COMMAND
);
if
(
inb
(
STATUS
)
&
RESETflag
)
/* reset flag STILL on */
{
BUGLVL
(
D_INIT
)
printk
(
"arcnet: probe failed. eternal reset flag1...(status=%Xh)
\n
"
,
BUGMSG
(
D_INIT
,
" probe failed. eternal reset flag1...(status=%Xh)
\n
"
,
inb
(
STATUS
));
return
ENODEV
;
}
...
...
@@ -827,15 +891,14 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
airq
=
autoirq_report
(
0
);
BUGLVL
(
D_INIT
)
if
(
airq
)
printk
(
"
arcnet: autoirq is %d
\n
"
,
airq
);
printk
(
"
%6s: autoirq is %d
\n
"
,
dev
->
name
,
airq
);
/* if there was no autoirq AND the user hasn't set any defaults,
* give up.
*/
if
(
!
airq
&&
!
(
dev
->
base_addr
&&
dev
->
irq
))
{
BUGLVL
(
D_INIT
)
printk
(
"arcnet: probe failed. no autoirq...
\n
"
);
BUGMSG
(
D_INIT
,
" probe failed. no autoirq...
\n
"
);
return
ENODEV
;
}
...
...
@@ -849,8 +912,7 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
if
(
inb
(
STATUS
)
&
RESETflag
)
/* reset flag STILL on */
{
BUGLVL
(
D_INIT
)
printk
(
"arcnet: probe failed. eternal reset flag...(status=%Xh)
\n
"
,
BUGMSG
(
D_INIT
,
" probe failed. eternal reset flag...(status=%Xh)
\n
"
,
inb
(
STATUS
));
return
ENODEV
;
}
...
...
@@ -865,13 +927,11 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
}
else
if
(
dev
->
irq
==
2
)
{
BUGLVL
(
D_NORMAL
)
printk
(
"arcnet: IRQ2 == IRQ9, don't worry.
\n
"
);
BUGMSG
(
D_NORMAL
,
"IRQ2 == IRQ9, don't worry.
\n
"
);
dev
->
irq
=
9
;
}
BUGLVL
(
D_INIT
)
printk
(
"arcnet: irq and base address seem okay. (%lXh, IRQ %d)
\n
"
,
BUGMSG
(
D_INIT
,
"irq and base address seem okay. (%lXh, IRQ %d)
\n
"
,
dev
->
base_addr
,
dev
->
irq
);
return
0
;
}
...
...
@@ -883,16 +943,14 @@ int arcnet_ioprobe(struct device *dev, short ioaddr)
*/
int
arcnet_memprobe
(
struct
device
*
dev
,
u_char
*
addr
)
{
BUGLVL
(
D_INIT
)
printk
(
"arcnet: probing memory at %lXh
\n
"
,(
u_long
)
addr
);
BUGMSG
(
D_INIT
,
"probing memory at %lXh
\n
"
,(
u_long
)
addr
);
dev
->
mem_start
=
0
;
/* ARCnet memory byte 0 is TESTvalue */
if
(
addr
[
0
]
!=
TESTvalue
)
{
BUGLVL
(
D_INIT
)
printk
(
"arcnet: probe failed. addr=%lXh, addr[0]=%Xh (not %Xh)
\n
"
,
BUGMSG
(
D_INIT
,
" probe failed. addr=%lXh, addr[0]=%Xh (not %Xh)
\n
"
,
(
unsigned
long
)
addr
,
addr
[
0
],
TESTvalue
);
return
ENODEV
;
}
...
...
@@ -901,8 +959,7 @@ int arcnet_memprobe(struct device *dev,u_char *addr)
addr
[
0
]
=
0x42
;
if
(
addr
[
0
]
!=
0x42
)
{
BUGLVL
(
D_INIT
)
printk
(
"arcnet: probe failed. addr=%lXh, addr[0]=%Xh (not 42h)
\n
"
,
BUGMSG
(
D_INIT
,
" probe failed. addr=%lXh, addr[0]=%Xh (not 42h)
\n
"
,
(
unsigned
long
)
addr
,
addr
[
0
]);
return
ENODEV
;
}
...
...
@@ -930,8 +987,7 @@ int arcnet_reset(struct device *dev)
outb
(
0
,
INTMASK
);
/* no IRQ's, please! */
BUGLVL
(
D_INIT
)
printk
(
"arcnet: Resetting %s (status=%Xh)
\n
"
,
BUGMSG
(
D_INIT
,
"Resetting %s (status=%Xh)
\n
"
,
dev
->
name
,
inb
(
STATUS
));
inb
(
RESET
);
/* Reset by reading this port */
...
...
@@ -946,8 +1002,7 @@ int arcnet_reset(struct device *dev)
cardmem
=
(
u_char
*
)
dev
->
mem_start
;
if
(
cardmem
[
0
]
!=
TESTvalue
)
{
BUGLVL
(
D_INIT
)
printk
(
"arcnet: reset failed: TESTvalue not present.
\n
"
);
BUGMSG
(
D_INIT
,
"reset failed: TESTvalue not present.
\n
"
);
return
1
;
}
lp
->
arcnum
=
cardmem
[
1
];
/* save address for later use */
...
...
@@ -1016,9 +1071,7 @@ static int arcnetE_init(struct device *dev)
dev
->
stop
=
NULL
;
dev
->
hard_start_xmit
=
arcnetE_send_packet
;
BUGLVL
(
D_EXTRA
)
printk
(
"%s: ARCnet Ethernet-Encap protocol initialized.
\n
"
,
dev
->
name
);
BUGMSG
(
D_EXTRA
,
"ARCnet Ethernet-Encap protocol initialized.
\n
"
);
return
0
;
}
...
...
@@ -1044,9 +1097,7 @@ static int arcnetS_init(struct device *dev)
#ifdef LINUX12
dev
->
type_trans
=
arcnetS_type_trans
;
#endif
BUGLVL
(
D_EXTRA
)
printk
(
"%s: ARCnet RFC1051 (NetBsd, AmiTCP) protocol initialized.
\n
"
,
dev
->
name
);
BUGMSG
(
D_EXTRA
,
"ARCnet RFC1051 (NetBsd, AmiTCP) protocol initialized.
\n
"
);
return
0
;
}
...
...
@@ -1075,7 +1126,7 @@ arcnet_open(struct device *dev)
if
(
dev
->
metric
>=
1000
)
{
arcnet_debug
=
dev
->
metric
-
1000
;
printk
(
"
arcnet: debug level set to %d
\n
"
,
arcnet_debug
);
printk
(
"
%6s: debug level set to %d
\n
"
,
dev
->
name
,
arcnet_debug
);
dev
->
metric
=
1
;
}
...
...
@@ -1083,7 +1134,7 @@ arcnet_open(struct device *dev)
irq2dev_map
[
dev
->
irq
]
=
dev
;
BUG
LVL
(
D_EXTRA
)
printk
(
"arcnet:
arcnet_open: resetting card.
\n
"
);
BUG
MSG
(
D_EXTRA
,
"
arcnet_open: resetting card.
\n
"
);
/* try to reset - twice if it fails the first time */
if
(
arcnet_reset
(
dev
)
&&
arcnet_reset
(
dev
))
...
...
@@ -1096,9 +1147,7 @@ arcnet_open(struct device *dev)
/* The RFC1201 driver is the default - just store */
lp
->
adev
=
dev
;
BUGLVL
(
D_EXTRA
)
printk
(
"%s: ARCnet RFC1201 protocol initialized.
\n
"
,
lp
->
adev
->
name
);
BUGMSG
(
D_EXTRA
,
"ARCnet RFC1201 protocol initialized.
\n
"
);
/* Initialize the ethernet-encap protocol driver */
lp
->
edev
=
(
struct
device
*
)
kmalloc
(
sizeof
(
struct
device
),
GFP_KERNEL
);
...
...
@@ -1135,7 +1184,6 @@ arcnet_open(struct device *dev)
outb
(
NORXflag
|
RECON_flag
,
INTMASK
);
MOD_INC_USE_COUNT
;
return
0
;
}
...
...
@@ -1151,6 +1199,10 @@ arcnet_close(struct device *dev)
TBUSY
=
1
;
START
=
0
;
/* very important! */
irq2dev_map
[
dev
->
irq
]
=
NULL
;
/* Flush TX and disable RX */
outb
(
0
,
INTMASK
);
/* no IRQ's (except RESET, of course) */
outb
(
NOTXcmd
,
COMMAND
);
/* stop transmit */
...
...
@@ -1178,10 +1230,9 @@ arcnet_close(struct device *dev)
kfree
(
lp
->
sdev
);
lp
->
sdev
=
NULL
;
/* Update the statistics here. */
/* Update the statistics here.
(not necessary in ARCnet)
*/
MOD_DEC_USE_COUNT
;
return
0
;
}
...
...
@@ -1193,25 +1244,28 @@ arcnet_close(struct device *dev)
* *
****************************************************************************/
/* Called by the kernel in order to transmit a packet.
/* Generic error checking routine for arcnet??_send_packet
*/
static
int
arcnet
A_send_packet
(
struct
sk_buff
*
skb
,
struct
device
*
dev
)
arcnet
_send_packet_bad
(
struct
sk_buff
*
skb
,
struct
device
*
dev
)
{
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)
dev
->
priv
;
int
ioaddr
=
dev
->
base_addr
;
lp
->
intx
++
;
BUGLVL
(
D_DURING
)
printk
(
"arcnet: transmit requested (status=%Xh, inTX=%d)
\n
"
,
BUGMSG
(
D_DURING
,
"transmit requested (status=%Xh, inTX=%d)
\n
"
,
inb
(
STATUS
),
lp
->
intx
);
if
(
lp
->
in_txhandler
)
{
printk
(
"arcnet: send_packet called while in txhandler!
\n
"
);
lp
->
intx
--
;
BUGMSG
(
D_NORMAL
,
"send_packet called while in txhandler!
\n
"
);
lp
->
stats
.
tx_dropped
++
;
return
1
;
}
if
(
lp
->
intx
>
1
)
{
BUGMSG
(
D_NORMAL
,
"send_packet called while intx!
\n
"
);
lp
->
stats
.
tx_dropped
++
;
return
1
;
}
...
...
@@ -1220,34 +1274,37 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
/* If we get here, some higher level has decided we are broken.
There should really be a "kick me" function call instead. */
int
tickssofar
=
jiffies
-
dev
->
trans_start
;
int
recbuf
=
lp
->
recbuf
;
/*int recbuf=lp->recbuf;*/
int
status
=
inb
(
STATUS
);
if
(
tickssofar
<
5
)
if
(
tickssofar
<
TX_TIMEOUT
)
{
BUGLVL
(
D_DURING
)
printk
(
"arcnet: premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d
\n
"
,
BUGMSG
(
D_DURING
,
"premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d
\n
"
,
status
,
tickssofar
,
lp
->
outgoing
.
skb
,
lp
->
outgoing
.
numsegs
,
lp
->
outgoing
.
segnum
);
lp
->
intx
--
;
return
1
;
}
BUGLVL
(
D_EXTRA
)
printk
(
"arcnet: transmit timed out (status=%Xh, inTX=%d, inTXh=%d, tickssofar=%d)
\n
"
,
status
,
lp
->
intx
,
lp
->
in_txhandler
,
tickssofar
);
outb
(
0
,
INTMASK
);
if
(
status
&
TXFREEflag
)
/* transmit _DID_ finish */
{
BUGMSG
(
D_EXTRA
,
"tx timed out - missed IRQ? (status=%Xh, inTX=%d, inTXh=%d, tickssofar=%d)
\n
"
,
status
,
lp
->
intx
,
lp
->
in_txhandler
,
tickssofar
);
lp
->
stats
.
tx_errors
++
;
}
else
{
BUGMSG
(
D_NORMAL
,
"tx timed out (status=%Xh, inTX=%d, inTXh=%d, tickssofar=%d)
\n
"
,
status
,
lp
->
intx
,
lp
->
in_txhandler
,
tickssofar
);
lp
->
stats
.
tx_errors
++
;
lp
->
stats
.
tx_aborted_errors
++
;
/* Try to restart the adaptor. */
/*arcnet_reset(dev);*/
outb
(
0
,
INTMASK
);
if
(
status
&
NORXflag
)
EnableReceiver
();
if
(
!
(
status
&
TXFREEflag
))
outb
(
NOTXcmd
,
COMMAND
);
/*dev->trans_start = jiffies;*/
}
if
(
lp
->
outgoing
.
skb
)
{
...
...
@@ -1257,12 +1314,8 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
lp
->
outgoing
.
skb
=
NULL
;
TBUSY
=
0
;
lp
->
intx
--
;
/*lp->intx=0;*/
/*lp->in_txhandler=0;*/
lp
->
txready
=
0
;
lp
->
sending
=
0
;
/*mark_bh(NET_BH);*/
outb
(
NORXflag
|
RECON_flag
,
INTMASK
);
...
...
@@ -1273,23 +1326,22 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
we are passed NULL. Caution: dev_tint() handles the cli()/sti()
itself. */
if
(
skb
==
NULL
)
{
printk
(
"arcnet: tx passed null skb (status=%Xh, inTX=%d, tickssofar=%ld)
\n
"
,
inb
(
STATUS
),
lp
->
intx
,
jiffies
-
dev
->
trans_start
);
printk
(
"%6s: tx passed null skb (status=%Xh, inTX=%d, tickssofar=%ld)
\n
"
,
dev
->
name
,
inb
(
STATUS
),
lp
->
intx
,
jiffies
-
dev
->
trans_start
);
lp
->
stats
.
tx_errors
++
;
dev_tint
(
dev
);
lp
->
intx
--
;
return
0
;
}
if
(
lp
->
txready
)
/* transmit already in progress! */
{
printk
(
"arcnet: trying to start new packet while busy! (status=%Xh)
\n
"
,
inb
(
STATUS
));
/*printk("arcnet: marking as not ready.\n");*/
printk
(
"%6s: trying to start new packet while busy! (status=%Xh)
\n
"
,
dev
->
name
,
inb
(
STATUS
));
outb
(
0
,
INTMASK
);
outb
(
NOTXcmd
,
COMMAND
);
/* abort current send */
arcnet_inthandler
(
dev
);
/* fake an interrupt */
lp
->
stats
.
tx_errors
++
;
lp
->
intx
--
;
lp
->
stats
.
tx_fifo_errors
++
;
lp
->
txready
=
0
;
/* we definitely need this line! */
return
1
;
...
...
@@ -1299,14 +1351,38 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
if
(
set_bit
(
0
,
(
void
*
)
&
dev
->
tbusy
)
!=
0
)
{
printk
(
"arcnet: transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)
\n
"
,
inb
(
STATUS
),
lp
->
intx
,
jiffies
-
dev
->
trans_start
);
lp
->
intx
--
;
printk
(
"%6s: transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)
\n
"
,
dev
->
name
,
inb
(
STATUS
),
lp
->
intx
,
jiffies
-
dev
->
trans_start
);
lp
->
stats
.
tx_errors
++
;
lp
->
stats
.
tx_fifo_errors
++
;
return
-
EBUSY
;
}
else
{
return
0
;
}
/* Called by the kernel in order to transmit a packet.
*/
static
int
arcnetA_send_packet
(
struct
sk_buff
*
skb
,
struct
device
*
dev
)
{
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)
dev
->
priv
;
int
ioaddr
=
dev
->
base_addr
,
bad
;
struct
Outgoing
*
out
=&
(
lp
->
outgoing
);
BUGMSG
(
D_DURING
,
"transmit requested (status=%Xh, inTX=%d)
\n
"
,
inb
(
STATUS
),
lp
->
intx
);
lp
->
intx
++
;
bad
=
arcnet_send_packet_bad
(
skb
,
dev
);
if
(
bad
)
{
lp
->
intx
--
;
return
bad
;
}
TBUSY
=
1
;
out
->
length
=
1
<
skb
->
len
?
skb
->
len
:
1
;
...
...
@@ -1326,18 +1402,16 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
out
->
hdr
->
sequence
=
(
lp
->
sequence
++
);
if
(
lp
->
txready
&&
inb
(
STATUS
)
&
TXFREEflag
)
arcnetAS_go_tx
(
dev
);
/*arcnet_go_tx(dev);*/
/* Make sure buffers are clear */
/* fits in one packet? */
if
(
out
->
length
-
EXTRA_CLIENTDATA
<=
XMTU
)
{
BUGLVL
(
D_DURING
)
printk
(
"arcnet: not splitting %d-byte packet. (split_flag=%d)
\n
"
,
BUGMSG
(
D_DURING
,
"not splitting %d-byte packet. (split_flag=%d)
\n
"
,
out
->
length
,
out
->
hdr
->
split_flag
);
BUGLVL
(
D_EXTRA
)
if
(
out
->
hdr
->
split_flag
)
printk
(
"arcnet
: short packet has split_flag set?! (split_flag=%d)
\n
"
,
out
->
hdr
->
split_flag
);
printk
(
"%6s
: short packet has split_flag set?! (split_flag=%d)
\n
"
,
dev
->
name
,
out
->
hdr
->
split_flag
);
out
->
numsegs
=
1
;
out
->
segnum
=
1
;
arcnetAS_prepare_tx
(
dev
,
...
...
@@ -1351,10 +1425,8 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
dev_kfree_skb
(
out
->
skb
,
FREE_WRITE
);
out
->
skb
=
NULL
;
if
(
!
lp
->
sending
)
if
(
arcnet_go_tx
(
dev
,
1
)
)
{
arcnetAS_go_tx
(
dev
);
/* inform upper layers */
TBUSY
=
0
;
mark_bh
(
NET_BH
);
...
...
@@ -1371,12 +1443,11 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
out
->
segnum
=
0
;
BUGLVL
(
D_TX
)
printk
(
"arcnet:
packet (%d bytes) split into %d fragments:
\n
"
,
BUGMSG
(
D_TX
,
"
packet (%d bytes) split into %d fragments:
\n
"
,
out
->
length
,
out
->
numsegs
);
/* if a packet waiting, launch it */
if
(
lp
->
txready
&&
inb
(
STATUS
)
&
TXFREEflag
)
arcnetAS_go_tx
(
dev
);
arcnet_go_tx
(
dev
,
1
);
if
(
!
lp
->
txready
)
{
...
...
@@ -1384,12 +1455,10 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
* another.
*/
arcnetA_continue_tx
(
dev
);
if
(
!
lp
->
sending
)
if
(
arcnet_go_tx
(
dev
,
1
)
)
{
arcnetAS_go_tx
(
dev
);
arcnetA_continue_tx
(
dev
);
if
(
!
lp
->
sending
)
arcnetAS_go_tx
(
dev
);
arcnet_go_tx
(
dev
,
1
);
}
}
...
...
@@ -1405,147 +1474,101 @@ arcnetA_send_packet(struct sk_buff *skb, struct device *dev)
out
->
skb
=
NULL
;
}
}
}
lp
->
intx
--
;
lp
->
stats
.
tx_packets
++
;
dev
->
trans_start
=
jiffies
;
lp
->
intx
--
;
return
0
;
}
/* After an RFC1201 split packet has been set up, this function calls
* arcnetAS_prepare_tx to load the next segment into the card. This function
* does NOT automatically call arcnetAS_go_tx to allow for easier double-
* buffering.
/* Called by the kernel in order to transmit an ethernet-type packet.
*/
static
void
arcnetA_continue_tx
(
struct
device
*
dev
)
static
int
arcnetE_send_packet
(
struct
sk_buff
*
skb
,
struct
device
*
dev
)
{
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)
dev
->
priv
;
int
maxsegsize
=
XMTU
-
4
;
struct
Outgoing
*
out
=&
(
lp
->
outgoing
);
int
bad
;
union
ArcPacket
*
arcpacket
=
(
union
ArcPacket
*
)(
dev
->
mem_start
+
512
*
(
lp
->
txbuf
^
1
));
u_char
*
arcsoft
,
daddr
;
short
offset
,
length
=
skb
->
len
+
1
;
if
(
lp
->
txready
)
{
printk
(
"arcnet: continue_tx: called with packet in buffer!
\n
"
);
return
;
}
BUGMSG
(
D_DURING
,
"in arcnetE_send_packet (skb=%p)
\n
"
,
skb
);
if
(
out
->
segnum
>=
out
->
numsegs
)
lp
->
intx
++
;
bad
=
arcnet_send_packet_bad
(
skb
,
dev
);
if
(
bad
)
{
printk
(
"arcnet: continue_tx: building segment %d of %d!
\n
"
,
out
->
segnum
+
1
,
out
->
numsegs
)
;
lp
->
intx
--
;
return
bad
;
}
if
(
!
out
->
segnum
)
/* first packet */
out
->
hdr
->
split_flag
=
((
out
->
numsegs
-
2
)
<<
1
)
+
1
;
else
out
->
hdr
->
split_flag
=
out
->
segnum
<<
1
;
out
->
seglen
=
maxsegsize
;
if
(
out
->
seglen
>
out
->
dataleft
)
out
->
seglen
=
out
->
dataleft
;
BUGLVL
(
D_TX
)
printk
(
"arcnet: building packet #%d (%d bytes) of %d (%d total), splitflag=%d
\n
"
,
out
->
segnum
+
1
,
out
->
seglen
,
out
->
numsegs
,
out
->
length
,
out
->
hdr
->
split_flag
);
arcnetAS_prepare_tx
(
dev
,((
char
*
)
out
->
hdr
)
+
EXTRA_CLIENTDATA
,
sizeof
(
struct
ClientData
)
-
EXTRA_CLIENTDATA
,
out
->
data
,
out
->
seglen
,
out
->
hdr
->
daddr
,
1
);
out
->
dataleft
-=
out
->
seglen
;
out
->
data
+=
out
->
seglen
;
out
->
segnum
++
;
}
TBUSY
=
1
;
/* Given an skb, copy a packet into the ARCnet buffers for later transmission
* by arcnetAS_go_tx.
*/
static
void
arcnetAS_prepare_tx
(
struct
device
*
dev
,
u_char
*
hdr
,
int
hdrlen
,
char
*
data
,
int
length
,
int
daddr
,
int
exceptA
)
{
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)
dev
->
priv
;
struct
ClientData
*
arcsoft
;
union
ArcPacket
*
arcpacket
=
(
union
ArcPacket
*
)(
dev
->
mem_start
+
512
*
(
lp
->
txbuf
^
1
));
int
offset
;
if
(
length
>
XMTU
)
{
printk
(
"%6s: MTU must be <= 493 for ethernet encap (length=%d).
\n
"
,
dev
->
name
,
length
);
printk
(
"%6s: transmit aborted.
\n
"
,
dev
->
name
);
lp
->
txbuf
=
lp
->
txbuf
^
1
;
/* XOR with 1 to alternate between 2 and 3 */
dev_kfree_skb
(
skb
,
FREE_WRITE
);
return
0
;
}
length
+=
hdrlen
;
BUGMSG
(
D_DURING
,
"starting tx sequence...
\n
"
)
;
BUGLVL
(
D_TX
)
printk
(
"arcnet: arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph
\n
"
,
hdr
,
length
,
data
);
lp
->
txbuf
=
lp
->
txbuf
^
1
;
/* XOR with 1 to alternate btw 2 & 3 */
/* clean out the page to make debugging make more sense :) */
BUGLVL
(
D_DURING
)
memset
((
void
*
)
dev
->
mem_start
+
lp
->
txbuf
*
512
,
0x42
,
512
);
arcpacket
->
hardheader
.
destination
=
daddr
;
/* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */
if
(((
struct
ethhdr
*
)(
skb
->
data
))
->
h_dest
[
0
]
==
0xFF
)
daddr
=
arcpacket
->
hardheader
.
destination
=
0
;
else
daddr
=
arcpacket
->
hardheader
.
destination
=
((
struct
ethhdr
*
)(
skb
->
data
))
->
h_dest
[
5
];
/* load packet into shared memory */
if
(
length
<=
MTU
)
/* Normal (256-byte) Packet */
{
arcpacket
->
hardheader
.
offset1
=
offset
=
256
-
length
;
arcsoft
=
(
struct
ClientData
*
)
(
&
arcpacket
->
raw
[
offset
]);
}
else
if
(
length
>=
MinTU
)
/* Extended (512-byte) Packet */
offset
=
512
-
length
;
if
(
length
>
MTU
)
/* long/exception packet */
{
if
(
length
<
MinTU
)
offset
-=
3
;
arcpacket
->
hardheader
.
offset1
=
0
;
arcpacket
->
hardheader
.
offset2
=
offset
=
512
-
length
;
arcsoft
=
(
struct
ClientData
*
)
(
&
arcpacket
->
raw
[
offset
]);
arcpacket
->
hardheader
.
offset2
=
offset
;
}
else
if
(
exceptA
)
/* RFC1201 Exception P
acket */
else
/* short p
acket */
{
arcpacket
->
hardheader
.
offset1
=
0
;
arcpacket
->
hardheader
.
offset2
=
offset
=
512
-
length
-
4
;
arcsoft
=
(
struct
ClientData
*
)
(
&
arcpacket
->
raw
[
offset
+
4
]);
/* exception-specific stuff - these four bytes
* make the packet long enough to fit in a 512-byte
* frame.
*/
arcpacket
->
raw
[
offset
+
0
]
=
hdr
[
0
];
arcpacket
->
raw
[
offset
+
1
]
=
0xFF
;
/* FF flag */
arcpacket
->
raw
[
offset
+
2
]
=
0xFF
;
/* FF padding */
arcpacket
->
raw
[
offset
+
3
]
=
0xFF
;
/* FF padding */
arcpacket
->
hardheader
.
offset1
=
(
offset
-=
256
);
}
else
/* "other" Exception packet */
{
/* RFC1051 - set 4 trailing bytes to 0 */
memset
(
&
arcpacket
->
raw
[
508
],
0
,
4
);
/* now round up to MinTU */
arcpacket
->
hardheader
.
offset1
=
0
;
arcpacket
->
hardheader
.
offset2
=
offset
=
512
-
MinTU
;
arcsoft
=
(
struct
ClientData
*
)(
&
arcpacket
->
raw
[
offset
]);
}
BUGMSG
(
D_DURING
,
" length=%Xh, offset=%Xh, offset1=%Xh, offset2=%Xh
\n
"
,
length
,
offset
,
arcpacket
->
hardheader
.
offset1
,
arcpacket
->
hardheader
.
offset2
);
arcsoft
=&
arcpacket
->
raw
[
offset
];
arcsoft
[
0
]
=
ARC_P_ETHER
;
arcsoft
++
;
/* copy the packet into ARCnet shmem
* - the first bytes of ClientData header are skipped
*/
memcpy
((
u_char
*
)
arcsoft
,
(
u_char
*
)
hdr
,
hdrlen
);
memcpy
((
u_char
*
)
arcsoft
+
hdrlen
,
data
,
length
-
hdrlen
);
BUGMSG
(
D_DURING
,
"ready to memcpy
\n
"
);
memcpy
(
arcsoft
,
skb
->
data
,
skb
->
len
);
BUG
LVL
(
D_DURING
)
printk
(
"arcnet:
transmitting packet to station %02Xh (%d bytes)
\n
"
,
BUG
MSG
(
D_DURING
,
"
transmitting packet to station %02Xh (%d bytes)
\n
"
,
daddr
,
length
);
BUGLVL
(
D_TX
)
{
int
countx
,
county
;
printk
(
"
arcnet: packet dump [tx] follows:"
);
printk
(
"
%6s: packet dump [tx] follows:"
,
dev
->
name
);
for
(
county
=
0
;
county
<
16
+
(
length
>
MTU
)
*
16
;
county
++
)
for
(
county
=
0
;
county
<
16
+
(
length
>
=
240
)
*
16
;
county
++
)
{
printk
(
"
\n
[%04X] "
,
county
*
16
);
for
(
countx
=
0
;
countx
<
16
;
countx
++
)
...
...
@@ -1560,151 +1583,229 @@ arcnetAS_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,
lp
->
outgoing
.
lastload_dest
=
daddr
;
#endif
lp
->
txready
=
lp
->
txbuf
;
/* packet is ready for sending */
}
/* Actually start transmitting a packet that was placed in the card's
* buffer by arcnetAS_prepare_tx.
*/
static
void
arcnetAS_go_tx
(
struct
device
*
dev
)
{
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)
dev
->
priv
;
int
ioaddr
=
dev
->
base_addr
;
BUGLVL
(
D_DURING
)
printk
(
"arcnet: go_tx: status=%Xh
\n
"
,
inb
(
STATUS
));
dev_kfree_skb
(
skb
,
FREE_WRITE
);
if
(
!
(
inb
(
STATUS
)
&
TXFREEflag
)
||
!
lp
->
txready
)
return
;
if
(
arcnet_go_tx
(
dev
,
1
))
{
/* inform upper layers */
TBUSY
=
0
;
mark_bh
(
NET_BH
);
}
/* start sending */
outb
(
TXcmd
|
(
lp
->
txready
<<
3
),
COMMAND
);
dev
->
trans_start
=
jiffies
;
lp
->
intx
--
;
return
0
;
}
outb
(
TXFREEflag
|
NORXflag
|
RECON_flag
,
INTMASK
);
dev
->
trans_start
=
jiffies
;
lp
->
txready
=
0
;
lp
->
sending
++
;
#ifdef VERIFY_ACK
lp
->
outgoing
.
lasttrans_dest
=
lp
->
outgoing
.
lastload_dest
;
lp
->
outgoing
.
lastload_dest
=
0
;
#endif
}
/* Called by the kernel in order to transmit an ethernet-type packet.
/* Called by the kernel in order to transmit an RFC1051-type packet.
*/
static
int
arcnet
E
_send_packet
(
struct
sk_buff
*
skb
,
struct
device
*
dev
)
arcnet
S
_send_packet
(
struct
sk_buff
*
skb
,
struct
device
*
dev
)
{
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)
dev
->
priv
;
int
ioaddr
=
dev
->
base_addr
,
bad
,
length
;
struct
S_ClientData
*
hdr
=
(
struct
S_ClientData
*
)
skb
->
data
;
BUGLVL
(
D_DURING
)
printk
(
"%s: in arcnetE_send_packet (skb=%p)
\n
"
,
dev
->
name
,
skb
);
lp
->
intx
++
;
if
(
IF_TBUSY
)
{
/* If we get here, some higher level has decided we are broken.
There should really be a "kick me" function call instead. */
int
tickssofar
=
jiffies
-
dev
->
trans_start
;
if
(
tickssofar
<
10
)
return
1
;
printk
(
"%s: transmit timed out
\n
"
,
dev
->
name
);
BUGMSG
(
D_DURING
,
"transmit requested (status=%Xh, inTX=%d)
\n
"
,
inb
(
STATUS
),
lp
->
intx
);
/* Try to restart the adaptor. */
TBUSY
=
0
;
/*dev->trans_start = jiffies;*/
return
0
;
bad
=
arcnet_send_packet_bad
(
skb
,
dev
);
if
(
bad
)
{
lp
->
intx
--
;
return
bad
;
}
/* If some higher layer thinks we've missed an tx-done interrupt
we are passed NULL. Caution: dev_tint() handles the cli()/sti()
itself. */
if
(
skb
==
NULL
)
TBUSY
=
1
;
length
=
1
<
skb
->
len
?
skb
->
len
:
1
;
BUGLVL
(
D_SKB
)
{
dev_tint
(
dev
);
return
0
;
short
i
;
for
(
i
=
0
;
i
<
skb
->
len
;
i
++
)
{
if
(
i
%
16
==
0
)
printk
(
"
\n
[%04hX] "
,
i
);
printk
(
"%02hX "
,((
unsigned
char
*
)
skb
->
data
)[
i
]);
}
printk
(
"
\n
"
);
}
/*
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
);
else
/*
if (lp->txready && inb(STATUS)&TXFREEflag)
arcnet_go_tx(dev);
*/
/* fits in one packet? */
if
(
length
-
S_EXTRA_CLIENTDATA
<=
XMTU
)
{
union
ArcPacket
*
arcpacket
=
(
union
ArcPacket
*
)(
dev
->
mem_start
+
512
*
(
lp
->
txbuf
^
1
));
u_char
*
arcsoft
,
daddr
;
short
offset
,
length
=
skb
->
len
+
1
;
arcnetAS_prepare_tx
(
dev
,
skb
->
data
+
S_EXTRA_CLIENTDATA
,
sizeof
(
struct
S_ClientData
)
-
S_EXTRA_CLIENTDATA
,
skb
->
data
+
sizeof
(
struct
S_ClientData
),
length
-
sizeof
(
struct
S_ClientData
),
hdr
->
daddr
,
0
);
TBUSY
=
1
;
/* done right away */
dev_kfree_skb
(
skb
,
FREE_WRITE
);
if
(
length
>
XMTU
)
if
(
arcnet_go_tx
(
dev
,
1
)
)
{
printk
(
"arcnet: MTU for %s and %s must be <= 493 for ethernet encap.
\n
"
,
lp
->
adev
->
name
,
lp
->
edev
->
name
);
printk
(
"arcnet: transmit aborted.
\n
"
);
/* inform upper layers */
TBUSY
=
0
;
mark_bh
(
NET_BH
);
}
}
else
/* too big for one - not accepted */
{
printk
(
"arcnetS: packet too long (length=%d)
\n
"
,
length
);
dev_kfree_skb
(
skb
,
FREE_WRITE
);
lp
->
stats
.
tx_dropped
++
;
TBUSY
=
0
;
mark_bh
(
NET_BH
);
}
dev
->
trans_start
=
jiffies
;
lp
->
intx
--
;
return
0
;
}
/* After an RFC1201 split packet has been set up, this function calls
* arcnetAS_prepare_tx to load the next segment into the card. This function
* does NOT automatically call arcnet_go_tx.
*/
static
void
arcnetA_continue_tx
(
struct
device
*
dev
)
{
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)
dev
->
priv
;
int
maxsegsize
=
XMTU
-
4
;
struct
Outgoing
*
out
=&
(
lp
->
outgoing
);
if
(
lp
->
txready
)
{
printk
(
"%6s: continue_tx: called with packet in buffer!
\n
"
,
dev
->
name
);
return
;
}
BUGLVL
(
D_DURING
)
printk
(
"arcnet: starting tx sequence...
\n
"
);
if
(
out
->
segnum
>=
out
->
numsegs
)
{
printk
(
"%6s: continue_tx: building segment %d of %d!
\n
"
,
dev
->
name
,
out
->
segnum
+
1
,
out
->
numsegs
);
}
lp
->
txbuf
=
lp
->
txbuf
^
1
;
/* XOR with 1 to alternate btw 2 & 3 */
if
(
!
out
->
segnum
)
/* first packet */
out
->
hdr
->
split_flag
=
((
out
->
numsegs
-
2
)
<<
1
)
+
1
;
else
out
->
hdr
->
split_flag
=
out
->
segnum
<<
1
;
out
->
seglen
=
maxsegsize
;
if
(
out
->
seglen
>
out
->
dataleft
)
out
->
seglen
=
out
->
dataleft
;
BUGMSG
(
D_TX
,
"building packet #%d (%d bytes) of %d (%d total), splitflag=%d
\n
"
,
out
->
segnum
+
1
,
out
->
seglen
,
out
->
numsegs
,
out
->
length
,
out
->
hdr
->
split_flag
);
arcnetAS_prepare_tx
(
dev
,((
char
*
)
out
->
hdr
)
+
EXTRA_CLIENTDATA
,
sizeof
(
struct
ClientData
)
-
EXTRA_CLIENTDATA
,
out
->
data
,
out
->
seglen
,
out
->
hdr
->
daddr
,
1
);
out
->
dataleft
-=
out
->
seglen
;
out
->
data
+=
out
->
seglen
;
out
->
segnum
++
;
}
/* Given an skb, copy a packet into the ARCnet buffers for later transmission
* by arcnet_go_tx.
*/
static
void
arcnetAS_prepare_tx
(
struct
device
*
dev
,
u_char
*
hdr
,
int
hdrlen
,
char
*
data
,
int
length
,
int
daddr
,
int
exceptA
)
{
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)
dev
->
priv
;
struct
ClientData
*
arcsoft
;
union
ArcPacket
*
arcpacket
=
(
union
ArcPacket
*
)(
dev
->
mem_start
+
512
*
(
lp
->
txbuf
^
1
));
int
offset
;
lp
->
txbuf
=
lp
->
txbuf
^
1
;
/* XOR with 1 to alternate between 2 and 3 */
length
+=
hdrlen
;
BUGMSG
(
D_TX
,
"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph
\n
"
,
hdr
,
length
,
data
);
/* clean out the page to make debugging make more sense :) */
BUGLVL
(
D_DURING
)
memset
((
void
*
)
dev
->
mem_start
+
lp
->
txbuf
*
512
,
0x42
,
512
);
/* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */
if
(((
struct
ethhdr
*
)(
skb
->
data
))
->
h_dest
[
0
]
==
0xFF
)
daddr
=
arcpacket
->
hardheader
.
destination
=
0
;
else
daddr
=
arcpacket
->
hardheader
.
destination
=
((
struct
ethhdr
*
)(
skb
->
data
))
->
h_dest
[
5
];
arcpacket
->
hardheader
.
destination
=
daddr
;
/* load packet into shared memory */
offset
=
512
-
length
;
if
(
length
>
MTU
)
/* long/exception packet */
if
(
length
<=
MTU
)
/* Normal (256-byte) Packet */
{
arcpacket
->
hardheader
.
offset1
=
offset
=
256
-
length
;
arcsoft
=
(
struct
ClientData
*
)
(
&
arcpacket
->
raw
[
offset
]);
}
else
if
(
length
>=
MinTU
)
/* Extended (512-byte) Packet */
{
if
(
length
<
MinTU
)
offset
-=
3
;
arcpacket
->
hardheader
.
offset1
=
0
;
arcpacket
->
hardheader
.
offset2
=
offset
;
arcpacket
->
hardheader
.
offset2
=
offset
=
512
-
length
;
arcsoft
=
(
struct
ClientData
*
)
(
&
arcpacket
->
raw
[
offset
]);
}
else
/* short p
acket */
else
if
(
exceptA
)
/* RFC1201 Exception P
acket */
{
arcpacket
->
hardheader
.
offset1
=
(
offset
-=
256
);
arcpacket
->
hardheader
.
offset1
=
0
;
arcpacket
->
hardheader
.
offset2
=
offset
=
512
-
length
-
4
;
arcsoft
=
(
struct
ClientData
*
)
(
&
arcpacket
->
raw
[
offset
+
4
]);
/* exception-specific stuff - these four bytes
* make the packet long enough to fit in a 512-byte
* frame.
*/
arcpacket
->
raw
[
offset
+
0
]
=
hdr
[
0
];
arcpacket
->
raw
[
offset
+
1
]
=
0xFF
;
/* FF flag */
arcpacket
->
raw
[
offset
+
2
]
=
0xFF
;
/* FF padding */
arcpacket
->
raw
[
offset
+
3
]
=
0xFF
;
/* FF padding */
}
else
/* "other" Exception packet */
{
/* RFC1051 - set 4 trailing bytes to 0 */
memset
(
&
arcpacket
->
raw
[
508
],
0
,
4
);
BUGLVL
(
D_DURING
)
printk
(
"arcnet: length=%Xh, offset=%Xh, offset1=%Xh, offset2=%Xh
\n
"
,
length
,
offset
,
arcpacket
->
hardheader
.
offset1
,
arcpacket
->
hardheader
.
offset2
);
/* now round up to MinTU */
arcpacket
->
hardheader
.
offset1
=
0
;
arcpacket
->
hardheader
.
offset2
=
offset
=
512
-
MinTU
;
arcsoft
=
(
struct
ClientData
*
)(
&
arcpacket
->
raw
[
offset
]);
}
arcsoft
=&
arcpacket
->
raw
[
offset
];
arcsoft
[
0
]
=
ARC_P_ETHER
;
arcsoft
++
;
/* copy the packet into ARCnet shmem
* - the first bytes of ClientData header are skipped
*/
BUGLVL
(
D_DURING
)
printk
(
"arcnet: ready to memcpy
\n
"
);
memcpy
(
arcsoft
,
skb
->
data
,
skb
->
len
);
memcpy
((
u_char
*
)
arcsoft
,
(
u_char
*
)
hdr
,
hdrlen
);
memcpy
((
u_char
*
)
arcsoft
+
hdrlen
,
data
,
length
-
hdrlen
);
BUGLVL
(
D_DURING
)
printk
(
"arcnet: transmitting packet to station %02Xh (%d bytes)
\n
"
,
BUGMSG
(
D_DURING
,
"transmitting packet to station %02Xh (%d bytes)
\n
"
,
daddr
,
length
);
BUGLVL
(
D_TX
)
{
int
countx
,
county
;
printk
(
"arcnet: packet dump [tx] follows:"
);
printk
(
"%6s: packet dump [tx] follows:"
,
dev
->
name
);
for
(
county
=
0
;
county
<
16
+
(
length
>=
240
)
*
16
;
county
++
)
for
(
county
=
0
;
county
<
16
+
(
length
>
MTU
)
*
16
;
county
++
)
{
printk
(
"
\n
[%04X] "
,
county
*
16
);
for
(
countx
=
0
;
countx
<
16
;
countx
++
)
...
...
@@ -1715,194 +1816,57 @@ arcnetE_send_packet(struct sk_buff *skb, struct device *dev)
printk
(
"
\n
"
);
}
#ifdef VERIFY_ACK
#ifdef VERIFY_ACK
lp
->
outgoing
.
lastload_dest
=
daddr
;
#endif
#endif
lp
->
txready
=
lp
->
txbuf
;
/* packet is ready for sending */
arcnetAS_go_tx
(
dev
);
dev
->
trans_start
=
jiffies
;
}
dev_kfree_skb
(
skb
,
FREE_WRITE
);
return
0
;
}
/* Called by the kernel in order to transmit an RFC1051-type packet
.
/* Actually start transmitting a packet that was placed in the card's
* buffer by arcnetAS_prepare_tx. Returns 1 if a Tx is really started
.
*/
static
int
arcnet
S_send_packet
(
struct
sk_buff
*
skb
,
struct
device
*
dev
)
arcnet
_go_tx
(
struct
device
*
dev
,
int
enable_irq
)
{
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)
dev
->
priv
;
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)
dev
->
priv
;
int
ioaddr
=
dev
->
base_addr
;
lp
->
intx
++
;
BUGLVL
(
D_DURING
)
printk
(
"arcnetS: transmit requested (status=%Xh, inTX=%d)
\n
"
,
inb
(
STATUS
),
lp
->
intx
);
if
(
lp
->
in_txhandler
)
{
printk
(
"arcnetS: send_packet called while in txhandler!
\n
"
);
lp
->
intx
--
;
return
1
;
}
if
(
IF_TBUSY
)
{
/* If we get here, some higher level has decided we are broken.
There should really be a "kick me" function call instead. */
int
tickssofar
=
jiffies
-
dev
->
trans_start
;
int
recbuf
=
lp
->
recbuf
;
int
status
=
inb
(
STATUS
);
if
(
tickssofar
<
5
)
{
BUGLVL
(
D_DURING
)
printk
(
"arcnetS: premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d
\n
"
,
status
,
tickssofar
,
lp
->
outgoing
.
skb
,
lp
->
outgoing
.
numsegs
,
lp
->
outgoing
.
segnum
);
lp
->
intx
--
;
return
1
;
}
BUGLVL
(
D_EXTRA
)
printk
(
"arcnetS: transmit timed out (status=%Xh, inTX=%d, inTXh=%d, tickssofar=%d)
\n
"
,
status
,
lp
->
intx
,
lp
->
in_txhandler
,
tickssofar
);
lp
->
stats
.
tx_errors
++
;
/* Try to restart the adaptor. */
/*arcnet_reset(dev);*/
BUGMSG
(
D_DURING
,
"go_tx: status=%Xh
\n
"
,
inb
(
STATUS
));
outb
(
0
,
INTMASK
);
if
(
status
&
NORXflag
)
EnableReceiver
();
if
(
!
(
status
&
TXFREEflag
))
outb
(
NOTXcmd
,
COMMAND
);
/*dev->trans_start = jiffies;*/
if
(
lp
->
outgoing
.
skb
)
if
(
lp
->
sending
||
!
lp
->
txready
)
{
dev_kfree_skb
(
lp
->
outgoing
.
skb
,
FREE_WRITE
);
lp
->
stats
.
tx_dropped
++
;
}
lp
->
outgoing
.
skb
=
NULL
;
TBUSY
=
0
;
lp
->
intx
--
;
/*lp->intx=0;*/
/*lp->in_txhandler=0;*/
lp
->
txready
=
0
;
lp
->
sending
=
0
;
/*mark_bh(NET_BH);*/
if
(
enable_irq
)
{
if
(
lp
->
sending
)
outb
(
TXFREEflag
|
NORXflag
|
RECON_flag
,
INTMASK
);
else
outb
(
NORXflag
|
RECON_flag
,
INTMASK
);
return
1
;
}
/* If some higher layer thinks we've missed a tx-done interrupt
we are passed NULL. Caution: dev_tint() handles the cli()/sti()
itself. */
if
(
skb
==
NULL
)
{
printk
(
"arcnetS: tx passed null skb (status=%Xh, inTX=%d, tickssofar=%ld)
\n
"
,
inb
(
STATUS
),
lp
->
intx
,
jiffies
-
dev
->
trans_start
);
dev_tint
(
dev
);
lp
->
intx
--
;
return
0
;
}
if
(
lp
->
txready
)
/* transmit already in progress! */
{
printk
(
"arcnetS: trying to start new packet while busy! (status=%Xh)
\n
"
,
inb
(
STATUS
));
/*printk("arcnetS: marking as not ready.\n");*/
outb
(
0
,
INTMASK
);
outb
(
NOTXcmd
,
COMMAND
);
/* abort current send */
arcnet_inthandler
(
dev
);
/* fake an interrupt */
lp
->
stats
.
tx_errors
++
;
lp
->
intx
--
;
lp
->
txready
=
0
;
/* we definitely need this line! */
return
1
;
}
/* 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
(
"arcnetS: transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)
\n
"
,
inb
(
STATUS
),
lp
->
intx
,
jiffies
-
dev
->
trans_start
);
lp
->
intx
--
;
return
-
EBUSY
;
}
else
{
int
length
;
struct
S_ClientData
*
hdr
=
(
struct
S_ClientData
*
)
skb
->
data
;
TBUSY
=
1
;
length
=
1
<
skb
->
len
?
skb
->
len
:
1
;
BUGLVL
(
D_SKB
)
{
short
i
;
for
(
i
=
0
;
i
<
skb
->
len
;
i
++
)
{
if
(
i
%
16
==
0
)
printk
(
"
\n
[%04hX] "
,
i
);
printk
(
"%02hX "
,((
unsigned
char
*
)
skb
->
data
)[
i
]);
}
printk
(
"
\n
"
);
}
if
(
lp
->
txready
&&
inb
(
STATUS
)
&
TXFREEflag
)
arcnetAS_go_tx
(
dev
);
/* fits in one packet? */
if
(
length
-
S_EXTRA_CLIENTDATA
<=
XMTU
)
{
arcnetAS_prepare_tx
(
dev
,
skb
->
data
+
S_EXTRA_CLIENTDATA
,
sizeof
(
struct
S_ClientData
)
-
S_EXTRA_CLIENTDATA
,
skb
->
data
+
sizeof
(
struct
S_ClientData
),
length
-
sizeof
(
struct
S_ClientData
),
hdr
->
daddr
,
0
);
/* start sending */
outb
(
TXcmd
|
(
lp
->
txready
<<
3
),
COMMAND
);
/* done right away */
dev_kfree_skb
(
skb
,
FREE_WRITE
);
lp
->
stats
.
tx_packets
++
;
lp
->
txready
=
0
;
lp
->
sending
++
;
if
(
!
lp
->
sending
)
{
arcnetAS_go_tx
(
dev
);
#ifdef VERIFY_ACK
lp
->
outgoing
.
lasttrans_dest
=
lp
->
outgoing
.
lastload_dest
;
lp
->
outgoing
.
lastload_dest
=
0
;
#endif
/* inform upper layers */
TBUSY
=
0
;
mark_bh
(
NET_BH
);
}
}
else
/* too big for one - not accepted */
{
printk
(
"arcnetS: packet too long (length=%d)
\n
"
,
length
);
dev_kfree_skb
(
skb
,
FREE_WRITE
);
lp
->
stats
.
tx_dropped
++
;
TBUSY
=
0
;
mark_bh
(
NET_BH
);
}
}
if
(
enable_irq
)
outb
(
TXFREEflag
|
NORXflag
|
RECON_flag
,
INTMASK
);
lp
->
intx
--
;
lp
->
stats
.
tx_packets
++
;
dev
->
trans_start
=
jiffies
;
return
0
;
return
1
;
}
/****************************************************************************
* *
* Interrupt handler *
...
...
@@ -1944,14 +1908,14 @@ arcnet_inthandler(struct device *dev)
if
(
IF_INTERRUPT
)
{
printk
(
"arcnet: DRIVER PROBLEM! Nested arcnet interrupts!
\n
"
);
printk
(
"%6s: DRIVER PROBLEM! Nested arcnet interrupts!
\n
"
,
dev
->
name
);
return
;
/* don't even try. */
}
outb
(
0
,
INTMASK
);
INTERRUPT
=
1
;
BUGLVL
(
D_DURING
)
printk
(
"arcnet: in net_interrupt (status=%Xh)
\n
"
,
inb
(
STATUS
));
BUGMSG
(
D_DURING
,
"in net_interrupt (status=%Xh)
\n
"
,
inb
(
STATUS
));
#if 1
/* Whatever you do, don't set this to 0. */
do
...
...
@@ -1959,17 +1923,22 @@ arcnet_inthandler(struct device *dev)
status
=
inb
(
STATUS
);
didsomething
=
0
;
#if 0 /* no longer necessary - doing checking in arcnet_interrupt now */
if (!dev->start)
{
BUGLVL
(
D_DURING
)
printk
(
"arcnet: ARCnet not yet initialized. irq ignored. (status=%Xh)
\n
"
,
BUGMSG(D_DURING,"ARCnet not yet initialized. irq ignored. (status=%Xh)\n",
status);
if (!(status&NORXflag))
outb(NORXflag|RECON_flag,INTMASK);
/* using dev->interrupt here instead of INTERRUPT
* because if dev->start is 0, the other devices
* probably do not exist.
*/
dev->interrupt=0;
return;
}
#endif
/* RESET flag was enabled - card is resetting and if RX
* is disabled, it's NOT because we just got a packet.
...
...
@@ -1977,28 +1946,89 @@ arcnet_inthandler(struct device *dev)
if
(
status
&
RESETflag
)
{
outb
(
CFLAGScmd
|
RESETclear
,
COMMAND
);
BUGLVL
(
D_INIT
)
printk
(
"arcnet: reset irq (status=%Xh)
\n
"
,
BUGMSG
(
D_INIT
,
"reset irq (status=%Xh)
\n
"
,
status
);
}
#ifdef DETECT_RECONFIGS
if
(
status
&
RECONflag
)
{
outb
(
CFLAGScmd
|
CONFIGclear
,
COMMAND
);
BUGLVL
(
D_EXTRA
)
printk
(
"arcnet: Network reconfiguration detected (status=%Xh)
\n
"
,
status
);
lp
->
stats
.
tx_carrier_errors
++
;
#ifdef SHOW_RECONFIGS
BUGMSG
(
D_NORMAL
,
"Network reconfiguration detected (status=%Xh)
\n
"
,
status
);
#endif
/* SHOW_RECONFIGS */
#ifdef RECON_THRESHOLD
/* is the RECON info empty or old? */
if
(
!
lp
->
first_recon
||
!
lp
->
last_recon
||
jiffies
-
lp
->
last_recon
>
HZ
*
10
)
{
if
(
lp
->
network_down
)
printk
(
"%6s: reconfiguration detected: cabling restored?
\n
"
,
dev
->
name
);
lp
->
first_recon
=
lp
->
last_recon
=
jiffies
;
lp
->
num_recons
=
lp
->
network_down
=
0
;
BUGMSG
(
D_DURING
,
"recon: clearing counters.
\n
"
);
}
#endif
else
/* add to current RECON counter */
{
lp
->
last_recon
=
jiffies
;
lp
->
num_recons
++
;
BUGMSG
(
D_DURING
,
"recon: counter=%d, time=%lds, net=%d
\n
"
,
lp
->
num_recons
,
(
lp
->
last_recon
-
lp
->
first_recon
)
/
HZ
,
lp
->
network_down
);
/* if network is marked up;
* and first_recon and last_recon are 60+ sec
* apart;
* and the average no. of recons counted is
* > RECON_THRESHOLD/min;
* then print a warning message.
*/
if
(
!
lp
->
network_down
&&
(
lp
->
last_recon
-
lp
->
first_recon
)
<=
HZ
*
60
&&
lp
->
num_recons
>=
RECON_THRESHOLD
)
{
lp
->
network_down
=
1
;
printk
(
"%6s: many reconfigurations detected: cabling problem?
\n
"
,
dev
->
name
);
}
else
if
(
!
lp
->
network_down
&&
lp
->
last_recon
-
lp
->
first_recon
>
HZ
*
60
)
{
/* reset counters if we've gone for
* over a minute.
*/
lp
->
first_recon
=
lp
->
last_recon
;
lp
->
num_recons
=
1
;
}
}
#endif
}
#ifdef RECON_THRESHOLD
else
if
(
lp
->
network_down
&&
jiffies
-
lp
->
last_recon
>
HZ
*
10
)
{
if
(
lp
->
network_down
)
printk
(
"%6s: cabling restored?
\n
"
,
dev
->
name
);
lp
->
first_recon
=
lp
->
last_recon
=
0
;
lp
->
num_recons
=
lp
->
network_down
=
0
;
BUGMSG
(
D_DURING
,
"not recon: clearing counters anyway.
\n
"
);
}
#endif
#endif
/* DETECT_RECONFIGS */
/* RX is inhibited - we must have received something. */
if
(
status
&
NORXflag
)
{
int
recbuf
=
lp
->
recbuf
=!
lp
->
recbuf
;
BUGLVL
(
D_DURING
)
printk
(
"arcnet: receive irq (status=%Xh)
\n
"
,
BUGMSG
(
D_DURING
,
"receive irq (status=%Xh)
\n
"
,
status
);
/* enable receive of our next packet */
...
...
@@ -2017,8 +2047,7 @@ arcnet_inthandler(struct device *dev)
lp
->
in_txhandler
++
;
lp
->
sending
--
;
BUGLVL
(
D_DURING
)
printk
(
"arcnet: TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)
\n
"
,
BUGMSG
(
D_DURING
,
"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)
\n
"
,
status
,
out
->
numsegs
,
out
->
segnum
,
out
->
skb
);
#ifdef VERIFY_ACK
...
...
@@ -2026,27 +2055,23 @@ arcnet_inthandler(struct device *dev)
{
if
(
lp
->
outgoing
.
lasttrans_dest
!=
0
)
{
printk
(
"
arcnet
: transmit was not acknowledged! (status=%Xh, dest=%d)
\n
"
,
status
,
printk
(
"
%6s
: transmit was not acknowledged! (status=%Xh, dest=%d)
\n
"
,
dev
->
name
,
status
,
lp
->
outgoing
.
lasttrans_dest
);
lp
->
stats
.
tx_errors
++
;
lp
->
stats
.
tx_carrier_errors
++
;
}
else
{
BUGLVL
(
D_DURING
)
printk
(
"arcnet: broadcast was not acknowledged; that's normal (status=%Xh, dest=%d)
\n
"
,
BUGMSG
(
D_DURING
,
"broadcast was not acknowledged; that's normal (status=%Xh, dest=%d)
\n
"
,
status
,
lp
->
outgoing
.
lasttrans_dest
);
}
}
#endif
/* send packet if there is one */
if
(
lp
->
txready
)
{
arcnetAS_go_tx
(
dev
);
arcnet_go_tx
(
dev
,
0
);
didsomething
++
;
}
if
(
lp
->
intx
)
{
...
...
@@ -2056,8 +2081,7 @@ arcnet_inthandler(struct device *dev)
if
(
!
lp
->
outgoing
.
skb
)
{
BUGLVL
(
D_DURING
)
printk
(
"arcnet: TX IRQ done: no split to continue.
\n
"
);
BUGMSG
(
D_DURING
,
"TX IRQ done: no split to continue.
\n
"
);
/* inform upper layers */
if
(
!
lp
->
txready
&&
IF_TBUSY
)
...
...
@@ -2070,15 +2094,12 @@ arcnet_inthandler(struct device *dev)
continue
;
}
/*lp->stats.tx_packets++;*/
/* if more than one segment, and not all segments
* are done, then continue xmit.
*/
if
(
out
->
segnum
<
out
->
numsegs
)
arcnetA_continue_tx
(
dev
);
if
(
lp
->
txready
&&
!
lp
->
sending
)
arcnetAS_go_tx
(
dev
);
arcnet_go_tx
(
dev
,
0
);
/* if segnum==numsegs, the transmission is finished;
* free the skb.
...
...
@@ -2102,13 +2123,19 @@ arcnet_inthandler(struct device *dev)
lp
->
in_txhandler
--
;
}
else
if
(
lp
->
txready
&&
!
lp
->
sending
&&
!
lp
->
intx
)
{
BUGMSG
(
D_NORMAL
,
"recovery from silent TX (status=%Xh)
\n
"
,
status
);
arcnet_go_tx
(
dev
,
0
);
didsomething
++
;
}
}
while
(
--
boguscount
&&
didsomething
);
BUGLVL
(
D_DURING
)
printk
(
"arcnet: net_interrupt complete (status=%Xh, count=%d)
\n\n
"
,
BUGMSG
(
D_DURING
,
"net_interrupt complete (status=%Xh, count=%d)
\n\n
"
,
inb
(
STATUS
),
boguscount
);
if
(
dev
->
start
&&
lp
->
sending
)
if
(
dev
->
start
&&
(
lp
->
sending
||
(
lp
->
txready
&&
!
lp
->
intx
))
)
outb
(
NORXflag
|
TXFREEflag
|
RECON_flag
,
INTMASK
);
else
outb
(
NORXflag
|
RECON_flag
,
INTMASK
);
...
...
@@ -2146,14 +2173,16 @@ arcnet_rx(struct device *dev,int recbuf)
short
length
,
offset
;
u_char
daddr
,
saddr
;
lp
->
stats
.
rx_packets
++
;
saddr
=
arcpacket
->
hardheader
.
source
;
daddr
=
arcpacket
->
hardheader
.
destination
;
/* if source is 0, it's a "used" packet! */
if
(
saddr
==
0
)
{
printk
(
"
arcnet
: discarding old packet. (status=%Xh)
\n
"
,
inb
(
STATUS
));
printk
(
"
%6s
: discarding old packet. (status=%Xh)
\n
"
,
dev
->
name
,
inb
(
STATUS
));
lp
->
stats
.
rx_errors
++
;
return
;
}
...
...
@@ -2173,8 +2202,7 @@ arcnet_rx(struct device *dev,int recbuf)
length
=
512
-
offset
;
}
BUGLVL
(
D_DURING
)
printk
(
"arcnet: received packet from %02Xh to %02Xh (%d bytes)
\n
"
,
BUGMSG
(
D_DURING
,
"received packet from %02Xh to %02Xh (%d bytes)
\n
"
,
saddr
,
daddr
,
length
);
/* call the right receiver for the protocol */
...
...
@@ -2194,8 +2222,10 @@ arcnet_rx(struct device *dev,int recbuf)
arcnetS_rx
(
lp
->
sdev
,
arcsoft
,
length
,
saddr
,
daddr
);
break
;
default:
printk
(
"arcnet: received unknown protocol %d (%Xh)
\n
"
,
arcsoft
[
0
],
arcsoft
[
0
]);
printk
(
"%6s: received unknown protocol %d (%Xh)
\n
"
,
dev
->
name
,
arcsoft
[
0
],
arcsoft
[
0
]);
lp
->
stats
.
rx_errors
++
;
lp
->
stats
.
rx_crc_errors
++
;
break
;
}
...
...
@@ -2203,7 +2233,7 @@ arcnet_rx(struct device *dev,int recbuf)
{
int
countx
,
county
;
printk
(
"
arcnet: packet dump [rx] follows:"
);
printk
(
"
%6s: packet dump [rx] follows:"
,
dev
->
name
);
for
(
county
=
0
;
county
<
16
+
(
length
>
240
)
*
16
;
county
++
)
{
...
...
@@ -2239,8 +2269,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
struct
sk_buff
*
skb
;
struct
ClientData
*
arcsoft
,
*
soft
;
BUGLVL
(
D_DURING
)
printk
(
"arcnet: it's an RFC1201 packet (length=%d)
\n
"
,
BUGMSG
(
D_DURING
,
"it's an RFC1201 packet (length=%d)
\n
"
,
length
);
/* compensate for EXTRA_CLIENTDATA (which isn't actually in the
...
...
@@ -2251,8 +2280,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
if
(
arcsoft
->
split_flag
==
0xFF
)
/* Exception Packet */
{
BUGLVL
(
D_DURING
)
printk
(
"arcnet: compensating for exception packet
\n
"
);
BUGMSG
(
D_DURING
,
"compensating for exception packet
\n
"
);
/* skip over 4-byte junkola */
arcsoft
=
(
struct
ClientData
*
)
...
...
@@ -2264,17 +2292,17 @@ arcnetA_rx(struct device *dev,u_char *buf,
{
struct
Incoming
*
in
=&
lp
->
incoming
[
saddr
];
BUG
LVL
(
D_RX
)
printk
(
"arcnet:
incoming is not split (splitflag=%d)
\n
"
,
BUG
MSG
(
D_RX
,
"
incoming is not split (splitflag=%d)
\n
"
,
arcsoft
->
split_flag
);
if
(
in
->
skb
)
/* already assembling one! */
{
BUG
LVL
(
D_EXTRA
)
printk
(
"arcnet:
aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)
\n
"
,
BUG
MSG
(
D_EXTRA
,
"
aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)
\n
"
,
in
->
sequence
,
arcsoft
->
split_flag
,
arcsoft
->
sequence
);
kfree_skb
(
in
->
skb
,
FREE_WRITE
);
lp
->
stats
.
tx_dropped
++
;
lp
->
stats
.
rx_errors
++
;
lp
->
stats
.
rx_missed_errors
++
;
in
->
skb
=
NULL
;
}
...
...
@@ -2282,7 +2310,8 @@ arcnetA_rx(struct device *dev,u_char *buf,
skb
=
alloc_skb
(
length
,
GFP_ATOMIC
);
if
(
skb
==
NULL
)
{
printk
(
"arcnet: Memory squeeze, dropping packet.
\n
"
);
printk
(
"%6s: Memory squeeze, dropping packet.
\n
"
,
dev
->
name
);
lp
->
stats
.
rx_dropped
++
;
return
;
}
...
...
@@ -2314,22 +2343,23 @@ arcnetA_rx(struct device *dev,u_char *buf,
if
(
!*
cptr
)
/* is saddr = 00? */
{
BUGLVL
(
D_EXTRA
)
printk
(
"arcnet: ARP source address was 00h, set to %02Xh.
\n
"
,
BUGMSG
(
D_EXTRA
,
"ARP source address was 00h, set to %02Xh.
\n
"
,
saddr
);
lp
->
stats
.
rx_crc_errors
++
;
*
cptr
=
saddr
;
}
else
BUGLVL
(
D_DURING
)
else
{
printk
(
"arcnet:
ARP source address (%Xh) is fine.
\n
"
,
BUGMSG
(
D_DURING
,
"
ARP source address (%Xh) is fine.
\n
"
,
*
cptr
);
}
}
else
{
printk
(
"arcnet: funny-shaped ARP packet. (%Xh, %Xh)
\n
"
,
arp
->
ar_hln
,
arp
->
ar_pln
);
lp
->
stats
.
rx_frame_errors
++
;
printk
(
"%6s: funny-shaped ARP packet. (%Xh, %Xh)
\n
"
,
dev
->
name
,
arp
->
ar_hln
,
arp
->
ar_pln
);
lp
->
stats
.
rx_errors
++
;
lp
->
stats
.
rx_crc_errors
++
;
}
}
...
...
@@ -2349,7 +2379,6 @@ arcnetA_rx(struct device *dev,u_char *buf,
#endif
netif_rx
(
skb
);
lp
->
stats
.
rx_packets
++
;
}
else
/* split packet */
{
...
...
@@ -2372,32 +2401,32 @@ arcnetA_rx(struct device *dev,u_char *buf,
struct
Incoming
*
in
=&
lp
->
incoming
[
saddr
];
BUG
LVL
(
D_RX
)
printk
(
"arcnet:
packet is split (splitflag=%d, seq=%d)
\n
"
,
BUG
MSG
(
D_RX
,
"
packet is split (splitflag=%d, seq=%d)
\n
"
,
arcsoft
->
split_flag
,
in
->
sequence
);
if
(
in
->
skb
&&
in
->
sequence
!=
arcsoft
->
sequence
)
{
BUG
LVL
(
D_EXTRA
)
printk
(
"arcnet:
wrong seq number, aborting assembly (expected=%d, seq=%d, splitflag=%d)
\n
"
,
BUG
MSG
(
D_EXTRA
,
"
wrong seq number, aborting assembly (expected=%d, seq=%d, splitflag=%d)
\n
"
,
in
->
sequence
,
arcsoft
->
sequence
,
arcsoft
->
split_flag
);
kfree_skb
(
in
->
skb
,
FREE_WRITE
);
in
->
skb
=
NULL
;
lp
->
stats
.
tx_dropped
++
;
lp
->
stats
.
rx_
fifo
_errors
++
;
lp
->
stats
.
rx_errors
++
;
lp
->
stats
.
rx_
missed
_errors
++
;
in
->
lastpacket
=
in
->
numpackets
=
0
;
}
if
(
arcsoft
->
split_flag
&
1
)
/* first packet in split */
{
BUG
LVL
(
D_RX
)
printk
(
"arcnet:
brand new splitpacket (splitflag=%d)
\n
"
,
BUG
MSG
(
D_RX
,
"
brand new splitpacket (splitflag=%d)
\n
"
,
arcsoft
->
split_flag
);
if
(
in
->
skb
)
/* already assembling one! */
{
BUG
LVL
(
D_EXTRA
)
printk
(
"arcnet:
aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)
\n
"
,
BUG
MSG
(
D_EXTRA
,
"
aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)
\n
"
,
in
->
sequence
,
arcsoft
->
split_flag
,
arcsoft
->
sequence
);
lp
->
stats
.
tx_dropped
++
;
lp
->
stats
.
rx_
over
_errors
++
;
lp
->
stats
.
rx_errors
++
;
lp
->
stats
.
rx_
missed
_errors
++
;
kfree_skb
(
in
->
skb
,
FREE_WRITE
);
}
...
...
@@ -2407,9 +2436,10 @@ arcnetA_rx(struct device *dev,u_char *buf,
if
(
in
->
numpackets
>
16
)
{
BUG
LVL
(
D_EXTRA
)
printk
(
"arcnet:
incoming packet more than 16 segments; dropping. (splitflag=%d)
\n
"
,
BUG
MSG
(
D_EXTRA
,
"
incoming packet more than 16 segments; dropping. (splitflag=%d)
\n
"
,
arcsoft
->
split_flag
);
lp
->
stats
.
rx_dropped
++
;
lp
->
stats
.
rx_errors
++
;
lp
->
stats
.
rx_length_errors
++
;
return
;
}
...
...
@@ -2417,7 +2447,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
+
sizeof
(
struct
ClientData
),
GFP_ATOMIC
);
if
(
skb
==
NULL
)
{
printk
(
"%s: (split) memory squeeze, dropping packet.
\n
"
,
printk
(
"%
6
s: (split) memory squeeze, dropping packet.
\n
"
,
dev
->
name
);
lp
->
stats
.
rx_dropped
++
;
return
;
...
...
@@ -2447,9 +2477,10 @@ arcnetA_rx(struct device *dev,u_char *buf,
*/
if
(
!
in
->
skb
)
{
BUG
LVL
(
D_EXTRA
)
printk
(
"arcnet:
can't continue split without starting first! (splitflag=%d, seq=%d)
\n
"
,
BUG
MSG
(
D_EXTRA
,
"
can't continue split without starting first! (splitflag=%d, seq=%d)
\n
"
,
arcsoft
->
split_flag
,
arcsoft
->
sequence
);
lp
->
stats
.
rx_errors
++
;
lp
->
stats
.
rx_missed_errors
++
;
return
;
}
...
...
@@ -2459,19 +2490,21 @@ arcnetA_rx(struct device *dev,u_char *buf,
/* harmless duplicate? ignore. */
if
(
packetnum
<=
in
->
lastpacket
-
1
)
{
BUG
LVL
(
D_EXTRA
)
printk
(
"arcnet:
duplicate splitpacket ignored! (splitflag=%d)
\n
"
,
BUG
MSG
(
D_EXTRA
,
"
duplicate splitpacket ignored! (splitflag=%d)
\n
"
,
arcsoft
->
split_flag
);
lp
->
stats
.
rx_errors
++
;
lp
->
stats
.
rx_frame_errors
++
;
return
;
}
/* "bad" duplicate, kill reassembly */
BUG
LVL
(
D_EXTRA
)
printk
(
"arcnet:
out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)
\n
"
,
BUG
MSG
(
D_EXTRA
,
"
out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)
\n
"
,
in
->
sequence
,
arcsoft
->
split_flag
,
arcsoft
->
sequence
);
kfree_skb
(
in
->
skb
,
FREE_WRITE
);
in
->
skb
=
NULL
;
lp
->
stats
.
tx_dropped
++
;
lp
->
stats
.
rx_
fifo
_errors
++
;
lp
->
stats
.
rx_errors
++
;
lp
->
stats
.
rx_
missed
_errors
++
;
in
->
lastpacket
=
in
->
numpackets
=
0
;
return
;
}
...
...
@@ -2494,8 +2527,12 @@ arcnetA_rx(struct device *dev,u_char *buf,
if
(
in
->
lastpacket
==
in
->
numpackets
)
{
if
(
!
skb
||
!
in
->
skb
)
printk
(
"arcnet: ?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)
\n
"
,
skb
,
in
->
skb
);
{
printk
(
"%6s: ?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)
\n
"
,
dev
->
name
,
skb
,
in
->
skb
);
}
else
{
in
->
skb
=
NULL
;
in
->
lastpacket
=
in
->
numpackets
=
0
;
...
...
@@ -2516,7 +2553,7 @@ arcnetA_rx(struct device *dev,u_char *buf,
#endif
netif_rx
(
skb
);
lp
->
stats
.
rx_packets
++
;
}
}
}
}
...
...
@@ -2531,13 +2568,12 @@ arcnetE_rx(struct device *dev,u_char *arcsoft,
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)
dev
->
priv
;
struct
sk_buff
*
skb
;
BUGLVL
(
D_DURING
)
printk
(
"arcnet: it's an ethernet-encap packet (length=%d)
\n
"
,
BUGMSG
(
D_DURING
,
"it's an ethernet-encap packet (length=%d)
\n
"
,
length
);
skb
=
alloc_skb
(
length
,
GFP_ATOMIC
);
if
(
skb
==
NULL
)
{
printk
(
"
arcnet: Memory squeeze, dropping packet.
\n
"
);
printk
(
"
%6s: Memory squeeze, dropping packet.
\n
"
,
dev
->
name
);
lp
->
stats
.
rx_dropped
++
;
return
;
}
...
...
@@ -2550,7 +2586,7 @@ arcnetE_rx(struct device *dev,u_char *arcsoft,
BUGLVL
(
D_SKB
)
{
short
i
;
printk
(
"
arcnet: rx skb dump follows:
\n
"
);
printk
(
"
%6s: rx skb dump follows:
\n
"
,
dev
->
name
);
for
(
i
=
0
;
i
<
skb
->
len
;
i
++
)
{
if
(
i
%
16
==
0
)
...
...
@@ -2566,7 +2602,6 @@ arcnetE_rx(struct device *dev,u_char *arcsoft,
#endif
netif_rx
(
skb
);
lp
->
stats
.
rx_packets
++
;
}
/* Packet receiver for RFC1051 packets;
...
...
@@ -2582,8 +2617,7 @@ arcnetS_rx(struct device *dev,u_char *buf,
arcsoft
=
(
struct
S_ClientData
*
)(
buf
-
S_EXTRA_CLIENTDATA
);
length
+=
S_EXTRA_CLIENTDATA
;
BUGLVL
(
D_DURING
)
printk
(
"arcnetS: it's an RFC1051 packet (length=%d)
\n
"
,
BUGMSG
(
D_DURING
,
"it's an RFC1051 packet (length=%d)
\n
"
,
length
);
...
...
@@ -2625,7 +2659,6 @@ arcnetS_rx(struct device *dev,u_char *buf,
#endif
netif_rx
(
skb
);
lp
->
stats
.
rx_packets
++
;
}
}
...
...
@@ -2659,7 +2692,7 @@ arcnet_get_stats(struct device *dev)
static
void
set_multicast_list
(
struct
device
*
dev
,
int
num_addrs
,
void
*
addrs
)
{
#if 0 /* no promiscuous mode at all on most ARCnet models */
#if 0 /* no promiscuous mode at all on most
(all?)
ARCnet models */
struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
short ioaddr = dev->base_addr;
...
...
@@ -2690,10 +2723,9 @@ int arcnetA_header(struct sk_buff *skb,struct device *dev,
#else
skb_push
(
skb
,
dev
->
hard_header_len
);
#endif
/* struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);*/
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)(
dev
->
priv
);
BUGLVL
(
D_DURING
)
printk
(
"arcnetA: create header from %d to %d; protocol %d (%Xh); size %u.
\n
"
,
BUGMSG
(
D_DURING
,
"create header from %d to %d; protocol %d (%Xh); size %u.
\n
"
,
saddr
?
*
(
u_char
*
)
saddr
:
-
1
,
daddr
?
*
(
u_char
*
)
daddr
:
-
1
,
type
,
type
,
len
);
...
...
@@ -2711,14 +2743,18 @@ int arcnetA_header(struct sk_buff *skb,struct device *dev,
head
->
protocol_id
=
ARC_P_RARP
;
break
;
case
ETH_P_IPX
:
case
ETH_P_802_3
:
case
ETH_P_802_2
:
head
->
protocol_id
=
ARC_P_IPX
;
break
;
case
ETH_P_ATALK
:
head
->
protocol_id
=
ARC_P_ATALK
;
break
;
default:
printk
(
"arcnet: I don't understand protocol %d (%Xh)
\n
"
,
type
,
type
);
printk
(
"%6s: I don't understand protocol %d (%Xh)
\n
"
,
dev
->
name
,
type
,
type
);
lp
->
stats
.
tx_errors
++
;
lp
->
stats
.
tx_aborted_errors
++
;
return
0
;
}
...
...
@@ -2771,24 +2807,24 @@ int arcnetS_header(struct sk_buff *skb,struct device *dev,
#else
skb_push
(
skb
,
dev
->
hard_header_len
);
#endif
/* struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);*/
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)(
dev
->
priv
);
/* set the protocol ID according to RFC1051 */
switch
(
type
)
{
case
ETH_P_IP
:
head
->
protocol_id
=
ARC_P_IP_RFC1051
;
BUGLVL
(
D_DURING
)
printk
(
"arcnetS: S_header: IP_RFC1051 packet.
\n
"
);
BUGMSG
(
D_DURING
,
"S_header: IP_RFC1051 packet.
\n
"
);
break
;
case
ETH_P_ARP
:
head
->
protocol_id
=
ARC_P_ARP_RFC1051
;
BUGLVL
(
D_DURING
)
printk
(
"arcnetS: S_header: ARP_RFC1051 packet.
\n
"
);
BUGMSG
(
D_DURING
,
"S_header: ARP_RFC1051 packet.
\n
"
);
break
;
default:
printk
(
"arcnetS: I don't understand protocol %d (%Xh)
\n
"
,
type
,
type
);
lp
->
stats
.
tx_errors
++
;
lp
->
stats
.
tx_aborted_errors
++
;
return
0
;
}
...
...
@@ -2827,6 +2863,7 @@ int arcnetA_rebuild_header(void *buff,struct device *dev,unsigned long dst,
struct
sk_buff
*
skb
)
{
struct
ClientData
*
head
=
(
struct
ClientData
*
)
buff
;
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)(
dev
->
priv
);
int
status
;
/*
...
...
@@ -2835,8 +2872,10 @@ int arcnetA_rebuild_header(void *buff,struct device *dev,unsigned long dst,
if
(
head
->
protocol_id
!=
ARC_P_IP
)
{
printk
(
"arcnet: I don't understand protocol type %d (%Xh) addresses!
\n
"
,
head
->
protocol_id
,
head
->
protocol_id
);
printk
(
"%6s: I don't understand protocol type %d (%Xh) addresses!
\n
"
,
dev
->
name
,
head
->
protocol_id
,
head
->
protocol_id
);
lp
->
stats
.
tx_errors
++
;
lp
->
stats
.
tx_aborted_errors
++
;
head
->
daddr
=
0
;
/*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/
return
0
;
...
...
@@ -2846,12 +2885,10 @@ int arcnetA_rebuild_header(void *buff,struct device *dev,unsigned long dst,
* Try and get ARP to resolve the header.
*/
#ifdef CONFIG_INET
BUGLVL
(
D_DURING
)
printk
(
"arcnetA: rebuild header from %d to %d; protocol %Xh
\n
"
,
BUGMSG
(
D_DURING
,
"rebuild header from %d to %d; protocol %Xh
\n
"
,
head
->
saddr
,
head
->
daddr
,
head
->
protocol_id
);
status
=
arp_find
(
&
(
head
->
daddr
),
dst
,
dev
,
dev
->
pa_addr
,
skb
)
?
1
:
0
;
BUGLVL
(
D_DURING
)
printk
(
"arcnetA: rebuilt: from %d to %d; protocol %Xh
\n
"
,
BUGMSG
(
D_DURING
,
" rebuilt: from %d to %d; protocol %Xh
\n
"
,
head
->
saddr
,
head
->
daddr
,
head
->
protocol_id
);
return
status
;
#else
...
...
@@ -2864,6 +2901,7 @@ int arcnetS_rebuild_header(void *buff,struct device *dev,unsigned long dst,
struct
sk_buff
*
skb
)
{
struct
S_ClientData
*
head
=
(
struct
S_ClientData
*
)
buff
;
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)(
dev
->
priv
);
/*
* Only ARP and IP are currently supported
...
...
@@ -2873,6 +2911,8 @@ int arcnetS_rebuild_header(void *buff,struct device *dev,unsigned long dst,
{
printk
(
"arcnetS: I don't understand protocol type %d (%Xh) addresses!
\n
"
,
head
->
protocol_id
,
head
->
protocol_id
);
lp
->
stats
.
tx_errors
++
;
lp
->
stats
.
tx_aborted_errors
++
;
head
->
daddr
=
0
;
/*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/
return
0
;
...
...
@@ -2922,14 +2962,14 @@ unsigned short arcnetA_type_trans(struct sk_buff *skb,struct device *dev)
case
ARC_P_IP
:
return
htons
(
ETH_P_IP
);
case
ARC_P_ARP
:
return
htons
(
ETH_P_ARP
);
case
ARC_P_RARP
:
return
htons
(
ETH_P_RARP
);
case
ARC_P_IPX
:
return
htons
(
ETH_P_
IPX
);
case
ARC_P_IPX
:
return
htons
(
ETH_P_
802_3
);
case
ARC_P_ATALK
:
return
htons
(
ETH_P_ATALK
);
/* untested appletalk */
case
ARC_P_LANSOFT
:
/* don't understand. fall through. */
default:
BUGLVL
(
D_EXTRA
)
printk
(
"arcnet: received packet of unknown protocol id %d (%Xh)
\n
"
,
BUGMSG
(
D_EXTRA
,
"received packet of unknown protocol id %d (%Xh)
\n
"
,
head
->
protocol_id
,
head
->
protocol_id
);
lp
->
stats
.
rx_frame_errors
++
;
lp
->
stats
.
rx_errors
++
;
lp
->
stats
.
rx_crc_errors
++
;
return
0
;
}
...
...
@@ -2943,7 +2983,7 @@ unsigned short arcnetS_type_trans(struct sk_buff *skb,struct device *dev)
struct
arcnet_local
*
lp
=
(
struct
arcnet_local
*
)
(
dev
->
priv
);
#ifdef LINUX12
head
=
(
struct
ClientData
*
)
skb
->
data
;
head
=
(
struct
S_
ClientData
*
)
skb
->
data
;
#else
/* Pull off the arcnet header. */
skb
->
mac
.
raw
=
skb
->
data
;
...
...
@@ -2966,10 +3006,10 @@ unsigned short arcnetS_type_trans(struct sk_buff *skb,struct device *dev)
case
ARC_P_IP_RFC1051
:
return
htons
(
ETH_P_IP
);
case
ARC_P_ARP_RFC1051
:
return
htons
(
ETH_P_ARP
);
default:
BUGLVL
(
D_EXTRA
)
printk
(
"arcnetS: received packet of unknown protocol id %d (%Xh)
\n
"
,
BUGMSG
(
D_EXTRA
,
"received packet of unknown protocol id %d (%Xh)
\n
"
,
head
->
protocol_id
,
head
->
protocol_id
);
lp
->
stats
.
rx_frame_errors
++
;
lp
->
stats
.
rx_errors
++
;
lp
->
stats
.
rx_crc_errors
++
;
return
0
;
}
...
...
drivers/net/eth16i.c
View file @
a89a2558
...
...
@@ -1170,7 +1170,6 @@ static void eth16i_select_regbank(unsigned char banknbr, short ioaddr)
}
#ifdef MODULE
char
kernel_version
[]
=
UTS_RELEASE
;
static
char
devicename
[
9
]
=
{
0
,
};
static
struct
device
dev_eth16i
=
{
devicename
,
...
...
drivers/pci/pci.c
View file @
a89a2558
...
...
@@ -168,8 +168,9 @@ struct pci_dev_info dev_info[] = {
DEVICE
(
ADAPTEC
,
ADAPTEC_7870
,
"AIC-7870"
),
DEVICE
(
ADAPTEC
,
ADAPTEC_7871
,
"AIC-7871"
),
DEVICE
(
ADAPTEC
,
ADAPTEC_7872
,
"AIC-7872"
),
DEVICE
(
ADAPTEC
,
ADAPTEC_7880
,
"AIC-7880"
),
DEVICE
(
ADAPTEC
,
ADAPTEC_7881
,
"AIC-7881"
),
DEVICE
(
ADAPTEC
,
ADAPTEC_7880
,
"AIC-7880U"
),
DEVICE
(
ADAPTEC
,
ADAPTEC_7881
,
"AIC-7881U"
),
DEVICE
(
ADAPTEC
,
ADAPTEC_7882
,
"AIC-7882U"
),
DEVICE
(
ATRONICS
,
ATRONICS_2015
,
"IDE-2015PL"
),
DEVICE
(
HER
,
HER_STING
,
"Stingray"
),
DEVICE
(
HER
,
HER_STINGARK
,
"Stingray ARK 2000PV"
)
...
...
drivers/scsi/aic7xxx.c
View file @
a89a2558
...
...
@@ -41,7 +41,7 @@
*
* -- Daniel M. Eischen, deischen@iworks.InterWorks.org, 04/03/95
*
* $Id: aic7xxx.c,v 2.
5 1995/09/20 05:18:18
deang Exp $
* $Id: aic7xxx.c,v 2.
10 1995/11/10 10:49:14
deang Exp $
*-M*************************************************************************/
#ifdef MODULE
...
...
@@ -73,7 +73,7 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
S_IFDIR
|
S_IRUGO
|
S_IXUGO
,
2
};
#define AIC7XXX_C_VERSION "$Revision: 2.
5
$"
#define AIC7XXX_C_VERSION "$Revision: 2.
10
$"
#define NUMBER(arr) (sizeof(arr) / sizeof(arr[0]))
#define MIN(a,b) ((a < b) ? a : b)
...
...
@@ -163,7 +163,7 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
* Define this to use polling rather than using kernel support for waking
* up a waiting process.
*/
#
undef
AIC7XXX_POLL
#
define
AIC7XXX_POLL
/*
* Controller type and options
...
...
@@ -172,9 +172,11 @@ typedef enum {
AIC_NONE
,
AIC_274x
,
/* EISA aic7770 */
AIC_284x
,
/* VLB aic7770 */
AIC_7870
,
/* PCI aic7870 */
AIC_7870
,
/* PCI aic7870
/aic7871 motherboard or 294x
*/
AIC_7850
,
/* PCI aic7850 */
AIC_7872
/* PCI aic7870 on 394x */
AIC_7872
,
/* PCI aic7870 on 394x */
AIC_7880
,
/* PCI aic7880/aic7881 motherboard or 294x Ultra */
AIC_7882
,
/* PCI aic7870 on 394x Ultra */
}
aha_type
;
typedef
enum
{
...
...
@@ -247,6 +249,21 @@ typedef enum {
#define ENAUTOATNP 0x02
#define SCSIRSTO 0x01
/*
* SCSI Transfer Control 0 Register (pp. 3-13).
* Controls the SCSI module data path.
*/
#define SXFRCTL0(x) ((x) + 0xC01ul)
#define DFON 0x80
#define DFPEXP 0x40
#define ULTRAEN 0x20
#define CLRSTCNT 0x10
#define SPIOEN 0x08
#define SCAMEN 0x04
#define CLRCHN 0x02
/* UNUSED 0x01 */
/*
* SCSI Transfer Control 1 Register (pp. 3-14,15).
* Controls the SCSI module data path.
...
...
@@ -394,28 +411,6 @@ typedef enum {
#define ONEBIT 0x08
/* UNUSED 0x07 */
/*
* Serial EEPROM Control (p. 4-92 in 7870 Databook)
* Controls the reading and writing of an external serial 1-bit
* EEPROM Device. In order to access the serial EEPROM, you must
* first set the SEEMS bit that generates a request to the memory
* port for access to the serial EEPROM device. When the memory
* port is not busy servicing another request, it reconfigures
* to allow access to the serial EEPROM. When this happens, SEERDY
* gets set high to verify that the memory port access has been
* granted. See aic7xxx_read_eprom for detailed information on
* the protocol necessary to read the serial EEPROM.
*/
#define SEECTL(x) ((x) + 0xC1Eul)
#define EXTARBACK 0x80
#define EXTARBREQ 0x40
#define SEEMS 0x20
#define SEERDY 0x10
#define SEECS 0x08
#define SEECK 0x04
#define SEEDO 0x02
#define SEEDI 0x01
/*
* SCSI Block Control (p. 3-32)
* Controls Bus type and channel selection. In a twin channel configuration
...
...
@@ -425,8 +420,11 @@ typedef enum {
*/
#define SBLKCTL(x) ((x) + 0xC1Ful)
/* UNUSED 0xC0 */
#define DIAGLEDEN 0x80
#define DIAGLEDON 0x40
#define AUTOFLUSHDIS 0x20
/* used for Rev C check */
/* UNUSED 0x10 */
#define SELBUS_MASK 0x0F
#define SELBUSB 0x08
/* UNUSED 0x04 */
#define SELWIDE 0x02
...
...
@@ -503,7 +501,7 @@ typedef enum {
#define PAUSE 0x04
#define INTEN 0x02
#define CHIPRST 0x01
#define REQ_PAUSE IRQMS |
PAUSE | INTEN
#define REQ_PAUSE IRQMS |
INTEN | PAUSE
#define UNPAUSE_274X IRQMS | INTEN
#define UNPAUSE_284X INTEN
#define UNPAUSE_294X IRQMS | INTEN
...
...
@@ -603,11 +601,64 @@ typedef enum {
/* ---------------- END AIC-7770 Register Definitions ----------------- */
/* --------------------- AHA-2840-only definitions -------------------- */
#define SEECTL_2840(x) ((x) + 0xCC0ul)
/* UNUSED 0xF8 */
#define CS_2840 0x04
#define CK_2840 0x02
#define DO_2840 0x01
#define STATUS_2840(x) ((x) + 0xCC1ul)
#define EEPROM_TF 0x80
#define BIOS_SEL 0x60
#define ADSEL 0x1E
#define DI_2840 0x01
/* --------------------- AIC-7870-only definitions -------------------- */
#define DSPCISTATUS(x) ((x) + 0xC86ul)
#define DFTHRESH 0xC0
/*
* Serial EEPROM Control (p. 4-92 in 7870 Databook)
* Controls the reading and writing of an external serial 1-bit
* EEPROM Device. In order to access the serial EEPROM, you must
* first set the SEEMS bit that generates a request to the memory
* port for access to the serial EEPROM device. When the memory
* port is not busy servicing another request, it reconfigures
* to allow access to the serial EEPROM. When this happens, SEERDY
* gets set high to verify that the memory port access has been
* granted. See aic7xxx_read_eprom for detailed information on
* the protocol necessary to read the serial EEPROM.
*/
#define SEECTL(x) ((x) + 0xC1Eul)
#define EXTARBACK 0x80
#define EXTARBREQ 0x40
#define SEEMS 0x20
#define SEERDY 0x10
#define SEECS 0x08
#define SEECK 0x04
#define SEEDO 0x02
#define SEEDI 0x01
#define DEVREVID 0x08ul
#define DEVSTATUS 0x40ul
#define MPORTMODE 0x04
/* aic7870 only */
#define RAMPSM 0x02
/* aic7870 only */
#define VOLSENSE 0x01
#define DEVCONFIG 0x41ul
#define SCBRAMSEL 0x80
#define MRDCEN 0x40
#define EXTSCBTIME 0x20
/* aic7870 only */
#define EXTSCBPEN 0x10
/* aic7870 only */
#define BERREN 0x08
#define DACEN 0x04
#define STPWLEVEL 0x02
#define DIFACTNEGEN 0x01
/* aic7870 only */
/* Scratch RAM offset definitions */
/* ---------------------- Scratch RAM Offsets ------------------------- */
...
...
@@ -726,9 +777,10 @@ struct seeprom_config {
/*
* Host Adapter Control Bits
*/
/* UNUSED
0x0003
*/
#define CF
WSTERM 0x0008
/* SCSI high byte termination (wide card
) */
/* UNUSED
0x0001
*/
#define CF
ULTRAEN 0x0002
/* Ultra SCSI speed enable (Ultra cards
) */
#define CFSTERM 0x0004
/* SCSI low byte termination (non-wide cards) */
#define CFWSTERM 0x0008
/* SCSI high byte termination (wide card) */
#define CFSPARITY 0x0010
/* SCSI parity */
/* UNUSED 0x0020 */
#define CFRESETB 0x0040
/* reset SCSI bus at IC initialization */
...
...
@@ -905,13 +957,13 @@ struct aic7xxx_scb {
/*-----------------end of hardware supported fields----------------*/
struct
aic7xxx_scb
*
next
;
/* next ptr when in free list */
Scsi_Cmnd
*
cmd
;
/* Scsi_Cmnd for this scb */
int
state
;
/* current state of scb */
#define SCB_FREE 0x00
#define SCB_ACTIVE 0x01
#define SCB_ABORTED 0x02
#define SCB_DEVICE_RESET 0x04
#define SCB_IMMED 0x08
#define SCB_SENSE 0x10
int
state
;
/* current state of scb */
unsigned
int
position
;
/* Position in scb array */
struct
scatterlist
sg
;
struct
scatterlist
sense_sg
;
...
...
@@ -947,7 +999,7 @@ generic_sense[] = { REQUEST_SENSE, 0, 0, 0, 255, 0 };
* of card. DON'T FORGET TO CHANGE THE SCB MASK IN THE
* SEQUENCER CODE IF THIS IS MODIFIED!
*/
#define AIC7XXX_MAXSCB
16
#define AIC7XXX_MAXSCB
255
/*
* Define a structure used for each host adapter, only one per IRQ.
...
...
@@ -958,6 +1010,8 @@ struct aic7xxx_host {
int
numscb
;
/* current number of scbs */
int
extended
;
/* extended xlate? */
aha_type
type
;
/* card type */
int
ultra_enabled
;
/* Ultra SCSI speed enabled */
int
chan_num
;
/* for 3940/3985, channel number */
aha_bus_type
bus_type
;
/* normal/twin/wide bus */
unsigned
char
a_scanned
;
/* 0 not scanned, 1 scanned */
unsigned
char
b_scanned
;
/* 0 not scanned, 1 scanned */
...
...
@@ -1010,7 +1064,10 @@ struct aic7xxx_host_config {
int
scsi_id_b
;
/* host SCSI ID B channel for twin cards */
int
extended
;
/* extended xlate? */
int
busrtime
;
/* bus release time */
int
walk_scbs
;
/* external SCB RAM detected; walk the scb array */
aha_type
type
;
/* card type */
int
ultra_enabled
;
/* Ultra SCSI speed enabled */
int
chan_num
;
/* for 3940/3985, channel number */
aha_bus_type
bus_type
;
/* normal/twin/wide bus */
aha_status_type
parity
;
/* bus parity enabled/disabled */
aha_status_type
low_term
;
/* bus termination low byte */
...
...
@@ -1024,22 +1081,30 @@ struct aic7xxx_host_config {
*/
static
struct
{
short
period
;
/* Rates in Ultra mode have bit 8 of sxfr set */
#define ULTRA_SXFR 0x100
short
rate
;
const
char
*
english
;
}
aic7xxx_syncrates
[]
=
{
{
100
,
0
,
"10.0"
},
{
125
,
1
,
"8.0"
},
{
150
,
2
,
"6.67"
},
{
175
,
3
,
"5.7"
},
{
200
,
4
,
"5.0"
},
{
225
,
5
,
"4.4"
},
{
250
,
6
,
"4.0"
},
{
275
,
7
,
"3.6"
}
{
50
,
0x100
,
"20.0"
},
{
62
,
0x110
,
"16.0"
},
{
75
,
0x120
,
"13.4"
},
{
100
,
0x140
,
"10.0"
},
{
100
,
0x000
,
"10.0"
},
{
125
,
0x010
,
"8.0"
},
{
150
,
0x020
,
"6.67"
},
{
175
,
0x030
,
"5.7"
},
{
200
,
0x040
,
"5.0"
},
{
225
,
0x050
,
"4.4"
},
{
250
,
0x060
,
"4.0"
},
{
275
,
0x070
,
"3.6"
}
};
static
int
num_aic7xxx_syncrates
=
sizeof
(
aic7xxx_syncrates
)
/
sizeof
(
aic7xxx_syncrates
[
0
]);
static
int
number_of_3940s
=
0
;
#ifdef AIC7XXX_DEBUG
static
void
...
...
@@ -1101,7 +1166,7 @@ debug_config(struct aic7xxx_host_config *p)
break
;
case
AIC_7870
:
printk
(
"AIC7870%s (PCI-bus):
\n
"
,
BUSW
[
p
->
bus_type
]);
printk
(
"AIC7870
/7871
%s (PCI-bus):
\n
"
,
BUSW
[
p
->
bus_type
]);
break
;
case
AIC_7850
:
...
...
@@ -1112,6 +1177,14 @@ debug_config(struct aic7xxx_host_config *p)
printk
(
"AIC7872%s (PCI-bus):
\n
"
,
BUSW
[
p
->
bus_type
]);
break
;
case
AIC_7880
:
printk
(
"AIC7880/7881%s (PCI-bus):
\n
"
,
BUSW
[
p
->
bus_type
]);
break
;
case
AIC_7882
:
printk
(
"AIC7882%s (PCI-bus):
\n
"
,
BUSW
[
p
->
bus_type
]);
break
;
default:
panic
(
"aic7xxx debug_config: internal error
\n
"
);
}
...
...
@@ -1160,6 +1233,7 @@ debug_config(struct aic7xxx_host_config *p)
}
}
#if 0
static void
debug_scb(struct aic7xxx_scb *scb)
{
...
...
@@ -1183,6 +1257,7 @@ debug_scb(struct aic7xxx_scb *scb)
(unsigned long) scb->next, (unsigned long) scb->cmd, scb->state,
scb->position);
}
#endif
#else
# define debug(fmt, args...)
...
...
@@ -1195,41 +1270,51 @@ debug_scb(struct aic7xxx_scb *scb)
* cards in the system. This should be fixed, but then,
* does anyone really have more than one in a machine?
*/
static
int
aic7xxx_extended
=
0
;
/* extended translation on? */
static
int
aic7xxx_no_reset
=
0
;
/* no resetting of SCSI bus */
static
unsigned
int
aic7xxx_extended
=
0
;
/* extended translation on? */
static
unsigned
int
aic7xxx_no_reset
=
0
;
/* no resetting of SCSI bus */
/*+F*************************************************************************
* Function:
* aic7xxx_setup
*
* Description:
* Handle Linux boot parameters.
* Handle Linux boot parameters. This routine allows for assigning a value
* to a parameter with a ':' between the parameter and the value.
* ie. aic7xxx=unpause:0x0A,extended
*-F*************************************************************************/
void
aic7xxx_setup
(
char
*
s
,
int
*
dummy
)
{
int
i
;
int
i
,
n
;
char
*
p
;
static
struct
{
const
char
*
name
;
int
*
flag
;
unsigned
int
*
flag
;
}
options
[]
=
{
{
"extended"
,
&
aic7xxx_extended
},
{
"no_reset"
,
&
aic7xxx_no_reset
},
{
NULL
,
NULL
}
{
NULL
,
NULL
}
};
for
(
p
=
strtok
(
s
,
","
);
p
;
p
=
strtok
(
NULL
,
","
))
{
for
(
i
=
0
;
options
[
i
].
name
;
i
++
)
{
if
(
!
strcmp
(
options
[
i
].
name
,
p
))
n
=
strlen
(
options
[
i
].
name
);
if
(
!
strncmp
(
options
[
i
].
name
,
p
,
n
))
{
if
(
p
[
n
]
==
':'
)
{
*
(
options
[
i
].
flag
)
=
simple_strtoul
(
p
+
n
+
1
,
NULL
,
0
);
}
else
{
*
(
options
[
i
].
flag
)
=
!
0
;
}
}
}
}
}
/*+F*************************************************************************
...
...
@@ -1532,8 +1617,9 @@ aic7xxx_length(Scsi_Cmnd *cmd, int sg_last)
* Look up the valid period to SCSIRATE conversion in our table
*-F*************************************************************************/
static
void
aic7xxx_scsirate
(
unsigned
char
*
scsirate
,
unsigned
char
period
,
unsigned
char
offset
,
int
target
,
char
channel
)
aic7xxx_scsirate
(
struct
aic7xxx_host
*
p
,
unsigned
char
*
scsirate
,
unsigned
char
period
,
unsigned
char
offset
,
int
target
,
char
channel
)
{
int
i
;
...
...
@@ -1541,8 +1627,38 @@ aic7xxx_scsirate(unsigned char *scsirate, unsigned char period,
{
if
((
aic7xxx_syncrates
[
i
].
period
-
period
)
>=
0
)
{
*
scsirate
=
(
aic7xxx_syncrates
[
i
].
rate
<<
4
)
|
(
offset
&
0x0F
);
printk
(
"aic7xxx: target %d, channel %c, now synchronous at %sMb/s, "
/*
* Watch out for Ultra speeds when ultra is not enabled and
* vice-versa.
*/
if
(
p
->
ultra_enabled
)
{
if
(
!
(
aic7xxx_syncrates
[
i
].
rate
&
ULTRA_SXFR
))
{
printk
(
"aic7xxx: target %d, channel %c, requests %sMB/s transfers, "
"but adapter in Ultra mode can only sync at 10MB/s or "
"above.
\n
"
,
target
,
channel
,
aic7xxx_syncrates
[
i
].
english
);
break
;
/* Use asynchronous transfers. */
}
}
else
{
/*
* Check for an Ultra device trying to negotiate an Ultra rate
* on an adapter with Ultra mode disabled.
*/
if
(
aic7xxx_syncrates
[
i
].
rate
&
ULTRA_SXFR
)
{
/*
* This should only happen if the driver is the first to negotiate
* and chooses a high rate. We'll just move down the table until
* we hit a non Ultra speed.
*/
continue
;
}
}
*
scsirate
=
(
aic7xxx_syncrates
[
i
].
rate
)
|
(
offset
&
0x0F
);
printk
(
"aic7xxx: target %d, channel %c, now synchronous at %sMB/s, "
"offset = 0x%x
\n
"
,
target
,
channel
,
aic7xxx_syncrates
[
i
].
english
,
offset
);
return
;
...
...
@@ -2079,6 +2195,7 @@ aic7xxx_reset_channel(struct aic7xxx_host *p, char channel,
outb
(
sblkctl
^
SELBUSB
,
SBLKCTL
(
base
));
aic7xxx_reset_current_bus
(
base
);
outb
(
sblkctl
,
SBLKCTL
(
base
));
UNPAUSE_SEQUENCER
(
p
);
}
/*
...
...
@@ -2280,7 +2397,7 @@ aic7xxx_isr(int irq, struct pt_regs * regs)
{
max_offset
=
0x0F
;
}
aic7xxx_scsirate
(
&
rate
,
transfer
,
MIN
(
offset
,
max_offset
),
scsi_id
,
channel
);
aic7xxx_scsirate
(
p
,
&
rate
,
transfer
,
MIN
(
offset
,
max_offset
),
scsi_id
,
channel
);
/*
* Preserve the wide transfer flag.
*/
...
...
@@ -3002,6 +3119,152 @@ aic7xxx_probe(int slot, int base)
return
(
AIC_NONE
);
}
/*+F*************************************************************************
* Function:
* read_2840_seeprom
*
* Description:
* Reads the 2840 serial EEPROM and returns 1 if successful and 0 if
* not successful.
*
* See read_seeprom (for the 2940) for the instruction set of the 93C46
* chip.
*
* The 2840 interface to the 93C46 serial EEPROM is through the
* STATUS_2840 and SEECTL_2840 registers. The CS_2840, CK_2840, and
* DO_2840 bits of the SEECTL_2840 register are connected to the chip
* select, clock, and data out lines respectively of the serial EEPROM.
* The DI_2840 bit of the STATUS_2840 is connected to the data in line
* of the serial EEPROM. The EEPROM_TF bit of STATUS_2840 register is
* useful in that it gives us an 800 nsec timer. After a read from the
* SEECTL_2840 register the timing flag is cleard and goes high 800 nsec
* later.
*
*-F*************************************************************************/
static
int
read_2840_seeprom
(
int
base
,
struct
seeprom_config
*
sc
)
{
int
i
=
0
,
k
=
0
;
unsigned
char
temp
;
unsigned
short
checksum
=
0
;
unsigned
short
*
seeprom
=
(
unsigned
short
*
)
sc
;
struct
seeprom_cmd
{
unsigned
char
len
;
unsigned
char
bits
[
3
];
};
struct
seeprom_cmd
seeprom_read
=
{
3
,
{
1
,
1
,
0
}};
#define CLOCK_PULSE(p) \
while ((inb(STATUS_2840(base)) & EEPROM_TF) == 0) \
{ \
;
/* Do nothing */
\
} \
(void) inb(SEECTL_2840(base));
/*
* Read the first 32 registers of the seeprom. For the 2840,
* the 93C46 SEEPROM is a 1024-bit device with 64 16-bit registers
* but only the first 32 are used by Adaptec BIOS. The loop
* will range from 0 to 31.
*/
for
(
k
=
0
;
k
<
(
sizeof
(
*
sc
)
/
2
);
k
++
)
{
/*
* Send chip select for one clock cycle.
*/
outb
(
CK_2840
|
CS_2840
,
SEECTL_2840
(
base
));
CLOCK_PULSE
(
base
);
/*
* Now we're ready to send the read command followed by the
* address of the 16-bit register we want to read.
*/
for
(
i
=
0
;
i
<
seeprom_read
.
len
;
i
++
)
{
temp
=
CS_2840
|
seeprom_read
.
bits
[
i
];
outb
(
temp
,
SEECTL_2840
(
base
));
CLOCK_PULSE
(
base
);
temp
=
temp
^
CK_2840
;
outb
(
temp
,
SEECTL_2840
(
base
));
CLOCK_PULSE
(
base
);
}
/*
* Send the 6 bit address (MSB first, LSB last).
*/
for
(
i
=
5
;
i
>=
0
;
i
--
)
{
temp
=
k
;
temp
=
(
temp
>>
i
)
&
1
;
/* Mask out all but lower bit. */
temp
=
CS_2840
|
temp
;
outb
(
temp
,
SEECTL_2840
(
base
));
CLOCK_PULSE
(
base
);
temp
=
temp
^
CK_2840
;
outb
(
temp
,
SEECTL_2840
(
base
));
CLOCK_PULSE
(
base
);
}
/*
* Now read the 16 bit register. An initial 0 precedes the
* register contents which begins with bit 15 (MSB) and ends
* with bit 0 (LSB). The initial 0 will be shifted off the
* top of our word as we let the loop run from 0 to 16.
*/
for
(
i
=
0
;
i
<=
16
;
i
++
)
{
temp
=
CS_2840
;
outb
(
temp
,
SEECTL_2840
(
base
));
CLOCK_PULSE
(
base
);
temp
=
temp
^
CK_2840
;
seeprom
[
k
]
=
(
seeprom
[
k
]
<<
1
)
|
(
inb
(
STATUS_2840
(
base
))
&
DI_2840
);
outb
(
temp
,
SEECTL_2840
(
base
));
CLOCK_PULSE
(
base
);
}
/*
* The serial EEPROM has a checksum in the last word. Keep a
* running checksum for all words read except for the last
* word. We'll verify the checksum after all words have been
* read.
*/
if
(
k
<
(
sizeof
(
*
sc
)
/
2
)
-
1
)
{
checksum
=
checksum
+
seeprom
[
k
];
}
/*
* Reset the chip select for the next command cycle.
*/
outb
(
0
,
SEECTL_2840
(
base
));
CLOCK_PULSE
(
base
);
outb
(
CK_2840
,
SEECTL_2840
(
base
));
CLOCK_PULSE
(
base
);
outb
(
0
,
SEECTL_2840
(
base
));
CLOCK_PULSE
(
base
);
}
#if 0
printk("Computed checksum 0x%x, checksum read 0x%x\n", checksum, sc->checksum);
printk("Serial EEPROM:");
for (k = 0; k < (sizeof(*sc) / 2); k++)
{
if (((k % 8) == 0) && (k != 0))
{
printk("\n ");
}
printk(" 0x%x", seeprom[k]);
}
printk("\n");
#endif
if
(
checksum
!=
sc
->
checksum
)
{
printk
(
"aic7xxx: SEEPROM checksum error, ignoring SEEPROM settings.
\n
"
);
return
(
0
);
}
return
(
1
);
#undef CLOCK_PULSE
}
/*+F*************************************************************************
* Function:
* read_seeprom
...
...
@@ -3052,9 +3315,9 @@ aic7xxx_probe(int slot, int base)
*
*-F*************************************************************************/
static
int
read_seeprom
(
int
base
,
struct
seeprom_config
*
sc
)
read_seeprom
(
int
base
,
int
offset
,
struct
seeprom_config
*
sc
)
{
int
i
=
0
,
k
=
0
;
int
i
=
0
,
k
;
unsigned
long
timeout
;
unsigned
char
temp
;
unsigned
short
checksum
=
0
;
...
...
@@ -3122,7 +3385,7 @@ read_seeprom(int base, struct seeprom_config *sc)
*/
for
(
i
=
5
;
i
>=
0
;
i
--
)
{
temp
=
k
;
temp
=
k
+
offset
;
temp
=
(
temp
>>
i
)
&
1
;
/* Mask out all but lower bit. */
temp
=
SEEMS
|
SEECS
|
(
temp
<<
1
);
outb
(
temp
,
SEECTL
(
base
));
...
...
@@ -3197,6 +3460,7 @@ read_seeprom(int base, struct seeprom_config *sc)
}
return
(
1
);
#undef CLOCK_PULSE
}
/*+F*************************************************************************
...
...
@@ -3207,10 +3471,10 @@ read_seeprom(int base, struct seeprom_config *sc)
* Return the maximum number of SCB's allowed for a given controller.
*-F*************************************************************************/
static
int
detect_maxscb
(
aha_type
type
,
int
base
)
detect_maxscb
(
aha_type
type
,
int
base
,
int
walk_scbs
)
{
unsigned
char
sblkctl_reg
;
int
maxscb
=
0
;
unsigned
char
sblkctl_reg
,
scb_byte
;
int
maxscb
=
0
,
i
;
switch
(
type
)
{
...
...
@@ -3248,14 +3512,15 @@ detect_maxscb(aha_type type, int base)
break
;
case
AIC_7870
:
case
AIC_7880
:
maxscb
=
16
;
break
;
case
AIC_7872
:
case
AIC_7882
:
/*
* Really has 255, but we'll wait to verify that we access
* them the same way and do not have to set the card to
* use the memory port to access external SCB RAM.
* Is suppose to have 255 SCBs, but we'll walk the SCBs
* looking for more if external RAM is detected.
*/
maxscb
=
16
;
break
;
...
...
@@ -3266,6 +3531,26 @@ detect_maxscb(aha_type type, int base)
*/
break
;
}
if
(
walk_scbs
)
{
/*
* This adapter has external SCB memory.
* Walk the SCBs to determine how many there are.
*/
i
=
0
;
while
(
i
<
AIC7XXX_MAXSCB
)
{
outb
(
i
,
SCBPTR
(
base
));
scb_byte
=
~
(
inb
(
SCBARRAY
(
base
)));
/* complement the byte */
outb
(
scb_byte
,
SCBARRAY
(
base
));
/* write it back out */
if
(
inb
(
SCBARRAY
(
base
))
!=
scb_byte
)
{
break
;
}
i
++
;
}
maxscb
=
i
;
}
return
(
maxscb
);
}
...
...
@@ -3278,41 +3563,35 @@ detect_maxscb(aha_type type, int base)
* Register a Adaptec aic7xxx chip SCSI controller with the kernel.
*-F*************************************************************************/
static
int
aic7xxx_register
(
Scsi_Host_Template
*
template
,
aha_type
type
,
int
base
,
unsigned
char
irq
)
aic7xxx_register
(
Scsi_Host_Template
*
template
,
struct
aic7xxx_host_config
*
config
)
{
static
const
char
*
board_name
[]
=
{
""
,
"274x"
,
"284x"
,
"7870"
,
"7850"
,
"7872"
};
static
const
char
*
board_name
[]
=
{
""
,
"274x"
,
"284x"
,
"7870"
,
"7850"
,
"7872"
,
"7881"
};
int
i
;
unsigned
char
sblkctl
;
int
max_targets
;
int
found
=
1
;
int
found
=
1
,
base
;
int
bios_disabled
=
0
;
unsigned
char
target_settings
;
unsigned
char
scsi_conf
,
host_conf
;
int
have_seeprom
=
0
;
struct
Scsi_Host
*
host
;
struct
aic7xxx_host
*
p
;
struct
aic7xxx_host_config
config
;
struct
seeprom_config
sc
;
config
.
type
=
type
;
config
.
base
=
base
;
config
.
irq
=
irq
;
config
.
parity
=
AIC_UNKNOWN
;
config
.
low_term
=
AIC_UNKNOWN
;
config
.
high_term
=
AIC_UNKNOWN
;
config
.
busrtime
=
0
;
base
=
config
->
base
;
/*
* Lock out other contenders for our i/o space.
*/
request_region
(
MINREG
(
base
),
MAXREG
(
base
)
-
MINREG
(
base
),
"aic7xxx"
);
switch
(
type
)
switch
(
config
->
type
)
{
case
AIC_274x
:
#if 0
printk("aha274x:
aic7770 hcntrl=0x%x\n", inb(HCNTRL(config.
base)));
printk("aha274x:
HCNTRL:0x%x\n", inb(HCNTRL(
base)));
#endif
/*
* For some 274x boards, we must clear the CHIPRST bit
...
...
@@ -3324,147 +3603,157 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
* trigger type (level or edge) and use this value
* for pausing and unpausing the sequencer.
*/
config
.
unpause
=
(
inb
(
HCNTRL
(
config
.
base
))
&
IRQMS
)
|
INTEN
;
config
.
pause
=
config
.
unpause
|
PAUSE
;
config
.
extended
=
aic7xxx_extended
;
/*
* I don't think we need to kick the reset again, the initial probe
* does a reset, it seems that this is kicking a dead horse here.
* So... I will try to just verify that the chip has come out of the
* reset state and continue the same as the 284x.
* In the Calgary version of the driver:
* 1) Chip Reset
* 2) Set unpause to IRQMS | INTEN
* 3) If an interrupt occured without any commands queued, the
* unpause was set to just INTEN
* I changed the initial reset code to just mask in the CHIPRST bit
* and try to leave the other settings alone.
*
* I don't think we need the warning about chip reset not being clear.
* On both my test machines (2842 & 2940), they work just fine with a
* HCNTRL() of 0x5 (PAUSE | CHIPRST). Notice though, the 274x also
* adds the INTEN flag, where neither the 284x or 294x do.
*/
outb
(
config
.
pause
|
CHIPRST
,
HCNTRL
(
config
.
base
));
config
->
unpause
=
(
inb
(
HCNTRL
(
base
))
&
IRQMS
)
|
INTEN
;
config
->
pause
=
config
->
unpause
|
PAUSE
;
config
->
extended
=
aic7xxx_extended
;
outb
(
config
->
pause
|
CHIPRST
,
HCNTRL
(
base
));
aic7xxx_delay
(
1
);
if
(
inb
(
HCNTRL
(
config
.
base
))
&
CHIPRST
)
if
(
inb
(
HCNTRL
(
base
))
&
CHIPRST
)
{
printk
(
"aic7xxx_register: Chip reset not cleared; clearing manually.
\n
"
);
}
outb
(
config
.
pause
,
HCNTRL
(
config
.
base
));
outb
(
config
->
pause
,
HCNTRL
(
base
));
/*
* Just to be on the safe side with the 274x, we will re-read the irq
* since there was some issue about reseting the board.
*/
config
.
irq
=
inb
(
HA_INTDEF
(
config
.
base
))
&
0x0F
;
config
->
irq
=
inb
(
HA_INTDEF
(
base
))
&
0x0F
;
if
((
inb
(
HA_274_BIOSCTRL
(
base
))
&
BIOSMODE
)
==
BIOSDISABLED
)
{
bios_disabled
=
1
;
}
host_conf
=
inb
(
HA_HOSTCONF
(
config
.
base
));
config
.
busrtime
=
host_conf
&
0x3C
;
host_conf
=
inb
(
HA_HOSTCONF
(
base
));
config
->
busrtime
=
host_conf
&
0x3C
;
/* XXX Is this valid for motherboard based controllers? */
/* Setup the FIFO threshold and the bus off time */
outb
(
host_conf
&
DFTHRSH
,
BUSSPD
(
config
.
base
));
outb
((
host_conf
<<
2
)
&
BOFF
,
BUSTIME
(
config
.
base
));
outb
(
host_conf
&
DFTHRSH
,
BUSSPD
(
base
));
outb
((
host_conf
<<
2
)
&
BOFF
,
BUSTIME
(
base
));
/*
* A reminder until this can be detected automatically.
*/
printk
(
"aha274x:
e
xtended translation %sabled
\n
"
,
config
.
extended
?
"en"
:
"dis"
);
printk
(
"aha274x:
E
xtended translation %sabled
\n
"
,
config
->
extended
?
"en"
:
"dis"
);
break
;
case
AIC_284x
:
#if 0
printk("aha284x:
aic7770 hcntrl=0x%x\n", inb(HCNTRL(config.
base)));
printk("aha284x:
HCNTRL:0x%x\n", inb(HCNTRL(
base)));
#endif
outb
(
CHIPRST
,
HCNTRL
(
config
.
base
));
config
.
unpause
=
UNPAUSE_284X
;
config
.
pause
=
REQ_PAUSE
;
/* DWG would like to be like the rest */
config
.
extended
=
aic7xxx_extended
;
config
.
irq
=
inb
(
HA_INTDEF
(
config
.
base
))
&
0x0F
;
outb
(
CHIPRST
,
HCNTRL
(
base
));
config
->
unpause
=
UNPAUSE_284X
;
config
->
pause
=
REQ_PAUSE
;
/* DWG would like to be like the rest */
aic7xxx_delay
(
1
);
outb
(
config
->
pause
,
HCNTRL
(
base
));
config
->
extended
=
aic7xxx_extended
;
config
->
irq
=
inb
(
HA_INTDEF
(
base
))
&
0x0F
;
if
((
inb
(
HA_274_BIOSCTRL
(
base
))
&
BIOSMODE
)
==
BIOSDISABLED
)
{
bios_disabled
=
1
;
}
host_conf
=
inb
(
HA_HOSTCONF
(
config
.
base
));
config
.
busrtime
=
host_conf
&
0x3C
;
host_conf
=
inb
(
HA_HOSTCONF
(
base
));
printk
(
"aha284x: Reading SEEPROM..."
);
have_seeprom
=
read_2840_seeprom
(
base
,
&
sc
);
if
(
!
have_seeprom
)
{
printk
(
"aha284x: Unable to read SEEPROM
\n
"
);
config
->
busrtime
=
host_conf
&
0x3C
;
}
else
{
printk
(
"done.
\n
"
);
config
->
extended
=
((
sc
.
bios_control
&
CFEXTEND
)
>>
7
);
config
->
scsi_id
=
(
sc
.
brtime_id
&
CFSCSIID
);
config
->
parity
=
(
sc
.
adapter_control
&
CFSPARITY
)
?
AIC_ENABLED
:
AIC_DISABLED
;
config
->
low_term
=
(
sc
.
adapter_control
&
CFSTERM
)
?
AIC_ENABLED
:
AIC_DISABLED
;
config
->
high_term
=
(
sc
.
adapter_control
&
CFWSTERM
)
?
AIC_ENABLED
:
AIC_DISABLED
;
config
->
busrtime
=
((
sc
.
brtime_id
&
CFBRTIME
)
>>
8
);
}
/* XXX Is this valid for motherboard based controllers? */
/* Setup the FIFO threshold and the bus off time */
outb
(
host_conf
&
DFTHRSH
,
BUSSPD
(
config
.
base
));
outb
((
host_conf
<<
2
)
&
BOFF
,
BUSTIME
(
config
.
base
));
outb
(
host_conf
&
DFTHRSH
,
BUSSPD
(
base
));
outb
((
host_conf
<<
2
)
&
BOFF
,
BUSTIME
(
base
));
/*
* A reminder until this can be detected automatically.
*/
printk
(
"aha284x: extended translation %sabled
\n
"
,
config
.
extended
?
"en"
:
"dis"
);
printk
(
"aha284x: Extended translation %sabled
\n
"
,
config
->
extended
?
"en"
:
"dis"
);
break
;
case
AIC_7850
:
case
AIC_7870
:
case
AIC_7872
:
case
AIC_7880
:
case
AIC_7882
:
#if 0
printk("aic%s
hcntrl=0x%x\n", board_name[type], inb(HCNTRL(config.
base)));
printk("aic%s
HCNTRL:0x%x\n", board_name[config->type], inb(HCNTRL(
base)));
#endif
outb
(
CHIPRST
,
HCNTRL
(
config
.
base
));
config
.
unpause
=
UNPAUSE_294X
;
config
.
pause
=
config
.
unpause
|
PAUSE
;
config
.
extended
=
aic7xxx_extended
;
config
.
scsi_id
=
7
;
outb
(
CHIPRST
,
HCNTRL
(
base
));
config
->
unpause
=
UNPAUSE_294X
;
config
->
pause
=
config
->
unpause
|
PAUSE
;
aic7xxx_delay
(
1
);
outb
(
config
->
pause
,
HCNTRL
(
base
));
config
->
extended
=
aic7xxx_extended
;
config
->
scsi_id
=
7
;
printk
(
"aic78xx: Reading SEEPROM...
"
);
have_seeprom
=
read_seeprom
(
base
,
&
sc
);
printk
(
"aic78xx: Reading SEEPROM..."
);
have_seeprom
=
read_seeprom
(
base
,
config
->
chan_num
*
(
sizeof
(
sc
)
/
2
),
&
sc
);
if
(
!
have_seeprom
)
{
printk
(
"aic78xx:
u
nable to read SEEPROM
\n
"
);
printk
(
"aic78xx:
U
nable to read SEEPROM
\n
"
);
}
else
{
printk
(
"done
\n
"
);
config
.
extended
=
((
sc
.
bios_control
&
CFEXTEND
)
>>
7
);
config
.
scsi_id
=
(
sc
.
brtime_id
&
CFSCSIID
);
config
.
parity
=
(
sc
.
adapter_control
&
CFSPARITY
)
?
printk
(
"done
.
\n
"
);
config
->
extended
=
((
sc
.
bios_control
&
CFEXTEND
)
>>
7
);
config
->
scsi_id
=
(
sc
.
brtime_id
&
CFSCSIID
);
config
->
parity
=
(
sc
.
adapter_control
&
CFSPARITY
)
?
AIC_ENABLED
:
AIC_DISABLED
;
config
.
low_term
=
(
sc
.
adapter_control
&
CFSTERM
)
?
config
->
low_term
=
(
sc
.
adapter_control
&
CFSTERM
)
?
AIC_ENABLED
:
AIC_DISABLED
;
config
.
high_term
=
(
sc
.
adapter_control
&
CFWSTERM
)
?
config
->
high_term
=
(
sc
.
adapter_control
&
CFWSTERM
)
?
AIC_ENABLED
:
AIC_DISABLED
;
config
.
busrtime
=
((
sc
.
brtime_id
&
CFBRTIME
)
>>
8
);
config
->
busrtime
=
((
sc
.
brtime_id
&
CFBRTIME
)
>>
8
);
if
(((
config
->
type
==
AIC_7880
)
||
(
config
->
type
==
AIC_7882
))
&&
(
sc
.
adapter_control
&
CFULTRAEN
))
{
printk
(
"aic7xxx: Enabling support for Ultra SCSI speed.
\n
"
);
config
->
ultra_enabled
=
TRUE
;
}
}
/*
* XXX - force data fifo threshold to 100%. Why does this
* need to be done?
*/
outb
(
inb
(
DSPCISTATUS
(
config
.
base
))
|
DFTHRESH
,
DSPCISTATUS
(
config
.
base
));
outb
(
config
.
scsi_id
|
DFTHRESH
,
HA_SCSICONF
(
config
.
base
));
outb
(
inb
(
DSPCISTATUS
(
base
))
|
DFTHRESH
,
DSPCISTATUS
(
base
));
outb
(
config
->
scsi_id
|
DFTHRESH
,
HA_SCSICONF
(
base
));
/*
* In case we are a wide card, place scsi ID in second conf byte.
*/
outb
(
config
.
scsi_id
,
(
HA_SCSICONF
(
config
.
base
)
+
1
));
outb
(
config
->
scsi_id
,
(
HA_SCSICONF
(
base
)
+
1
));
/*
* A reminder until this can be detected automatically.
*/
printk
(
"aic%s: extended translation %sabled
\n
"
,
board_name
[
type
],
config
.
extended
?
"en"
:
"dis"
);
printk
(
"aic%s: Extended translation %sabled
\n
"
,
board_name
[
config
->
type
],
config
->
extended
?
"en"
:
"dis"
);
break
;
default:
panic
(
"aic7xxx_register: internal error
\n
"
);
}
config
.
maxscb
=
detect_maxscb
(
type
,
base
);
config
->
maxscb
=
detect_maxscb
(
config
->
type
,
base
,
config
->
walk_scbs
);
if
((
config
.
type
==
AIC_274x
)
||
(
config
.
type
==
AIC_284x
))
if
((
config
->
type
==
AIC_274x
)
||
(
config
->
type
==
AIC_284x
))
{
if
(
config
.
pause
&
IRQMS
)
if
(
config
->
pause
&
IRQMS
)
{
printk
(
"aic7xxx: Using Level Sensitive Interrupts
\n
"
);
}
...
...
@@ -3478,35 +3767,35 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
* Read the bus type from the SBLKCTL register. Set the FLAGS
* register in the sequencer for twin and wide bus cards.
*/
sblkctl
=
inb
(
SBLKCTL
(
base
))
&
0x0F
;
/* mask out upper two bits */
switch
(
sblkctl
)
sblkctl
=
inb
(
SBLKCTL
(
base
))
;
switch
(
sblkctl
&
SELBUS_MASK
)
{
case
SELSINGLE
:
/* narrow/normal bus */
config
.
scsi_id
=
inb
(
HA_SCSICONF
(
base
))
&
0x07
;
config
.
bus_type
=
AIC_SINGLE
;
config
->
scsi_id
=
inb
(
HA_SCSICONF
(
base
))
&
0x07
;
config
->
bus_type
=
AIC_SINGLE
;
outb
(
SINGLE_BUS
,
HA_FLAGS
(
base
));
break
;
case
SELWIDE
:
/* Wide bus */
config
.
scsi_id
=
inb
(
HA_SCSICONF
(
base
)
+
1
)
&
0x0F
;
config
.
bus_type
=
AIC_WIDE
;
config
->
scsi_id
=
inb
(
HA_SCSICONF
(
base
)
+
1
)
&
0x0F
;
config
->
bus_type
=
AIC_WIDE
;
printk
(
"aic7xxx: Enabling wide channel of %s-Wide
\n
"
,
board_name
[
config
.
type
]);
board_name
[
config
->
type
]);
outb
(
WIDE_BUS
,
HA_FLAGS
(
base
));
break
;
case
SELBUSB
:
/* Twin bus */
config
.
scsi_id
=
inb
(
HA_SCSICONF
(
base
))
&
0x07
;
config
->
scsi_id
=
inb
(
HA_SCSICONF
(
base
))
&
0x07
;
#ifdef AIC7XXX_TWIN_SUPPORT
config
.
scsi_id_b
=
inb
(
HA_SCSICONF
(
base
)
+
1
)
&
0x07
;
config
.
bus_type
=
AIC_TWIN
;
config
->
scsi_id_b
=
inb
(
HA_SCSICONF
(
base
)
+
1
)
&
0x07
;
config
->
bus_type
=
AIC_TWIN
;
printk
(
"aic7xxx: Enabled channel B of %s-Twin
\n
"
,
board_name
[
config
.
type
]);
board_name
[
config
->
type
]);
outb
(
TWIN_BUS
,
HA_FLAGS
(
base
));
#else
config
.
bus_type
=
AIC_SINGLE
;
config
->
bus_type
=
AIC_SINGLE
;
printk
(
"aic7xxx: Channel B of %s-Twin will be ignored
\n
"
,
board_name
[
config
.
type
]);
board_name
[
config
->
type
]);
outb
(
0
,
HA_FLAGS
(
base
));
#endif
break
;
...
...
@@ -3519,12 +3808,11 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
}
/*
* Clear the upper two bits. For the 294x cards, clearing the
* upper two bits, will take the card out of diagnostic mode
* and make the host adatper LED follow bus activity (will not
* always be on).
* For the 294x cards, clearing DIAGLEDEN and DIAGLEDON, will
* take the card out of diagnostic mode and make the host adatper
* LED follow bus activity (will not always be on).
*/
outb
(
sblkctl
,
SBLKCTL
(
base
));
outb
(
sblkctl
&
~
(
DIAGLEDEN
|
DIAGLEDON
)
,
SBLKCTL
(
base
));
/*
* The IRQ level in i/o port 4 maps directly onto the real
...
...
@@ -3536,10 +3824,10 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
*
* The 294x cards (PCI) get their interrupt from PCI BIOS.
*/
if
(((
config
.
type
==
AIC_274x
)
||
(
config
.
type
==
AIC_284x
))
&&
(
config
.
irq
<
9
||
config
.
irq
>
15
))
if
(((
config
->
type
==
AIC_274x
)
||
(
config
->
type
==
AIC_284x
))
&&
(
config
->
irq
<
9
||
config
->
irq
>
15
))
{
printk
(
"aic7xxx uses unsupported IRQ level, ignoring
\n
"
);
printk
(
"aic7xxx uses unsupported IRQ level, ignoring
.
\n
"
);
return
(
0
);
}
...
...
@@ -3551,7 +3839,7 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
* proceed.
*/
#ifndef AIC7XXX_SHARE_IRQS
if
(
aic7xxx_boards
[
config
.
irq
]
!=
NULL
)
if
(
aic7xxx_boards
[
config
->
irq
]
!=
NULL
)
{
printk
(
"aic7xxx_register: Sharing of IRQs is not configured.
\n
"
);
return
(
0
);
...
...
@@ -3563,7 +3851,7 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
* the card - a lot of registers on it can't be read
* when the sequencer is active.
*/
debug_config
(
&
config
);
debug_config
(
config
);
/*
* Before registry, make sure that the offsets of the
...
...
@@ -3579,7 +3867,7 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
if
(
SG_STRUCT_CHECK
(
sg
))
{
printk
(
"aic7xxx warning: kernel scatter-gather "
"structures changed, disabling it
\n
"
);
"structures changed, disabling it
.
\n
"
);
template
->
sg_tablesize
=
SG_NONE
;
}
}
...
...
@@ -3593,15 +3881,15 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
* information when an IRQ is triggered.
*/
host
=
scsi_register
(
template
,
sizeof
(
struct
aic7xxx_host
));
host
->
can_queue
=
config
.
maxscb
;
host
->
can_queue
=
config
->
maxscb
;
host
->
cmd_per_lun
=
AIC7XXX_CMDS_PER_LUN
;
host
->
this_id
=
config
.
scsi_id
;
host
->
irq
=
config
.
irq
;
if
(
config
.
bus_type
==
AIC_WIDE
)
host
->
this_id
=
config
->
scsi_id
;
host
->
irq
=
config
->
irq
;
if
(
config
->
bus_type
==
AIC_WIDE
)
{
host
->
max_id
=
16
;
}
if
(
config
.
bus_type
==
AIC_TWIN
)
if
(
config
->
bus_type
==
AIC_TWIN
)
{
host
->
max_channel
=
1
;
}
...
...
@@ -3621,21 +3909,23 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
p
->
isr_count
=
0
;
p
->
a_scanned
=
0
;
p
->
b_scanned
=
0
;
p
->
base
=
config
.
base
;
p
->
maxscb
=
config
.
maxscb
;
p
->
base
=
base
;
p
->
maxscb
=
config
->
maxscb
;
p
->
numscb
=
0
;
p
->
extended
=
config
.
extended
;
p
->
type
=
config
.
type
;
p
->
bus_type
=
config
.
bus_type
;
p
->
extended
=
config
->
extended
;
p
->
type
=
config
->
type
;
p
->
ultra_enabled
=
config
->
ultra_enabled
;
p
->
chan_num
=
config
->
chan_num
;
p
->
bus_type
=
config
->
bus_type
;
p
->
have_seeprom
=
have_seeprom
;
p
->
seeprom
=
sc
;
p
->
free_scb
=
NULL
;
p
->
next
=
NULL
;
p
->
unpause
=
config
.
unpause
;
p
->
pause
=
config
.
pause
;
p
->
unpause
=
config
->
unpause
;
p
->
pause
=
config
->
pause
;
if
(
aic7xxx_boards
[
config
.
irq
]
==
NULL
)
if
(
aic7xxx_boards
[
config
->
irq
]
==
NULL
)
{
/*
* Warning! This must be done before requesting the irq. It is
...
...
@@ -3644,15 +3934,15 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
* kernel, an interrupt is triggered immediately. Therefore, we
* must ensure the board data is correctly set before the request.
*/
aic7xxx_boards
[
config
.
irq
]
=
host
;
aic7xxx_boards
[
config
->
irq
]
=
host
;
/*
* Register IRQ with the kernel.
*/
if
(
request_irq
(
config
.
irq
,
aic7xxx_isr
,
SA_INTERRUPT
,
"aic7xxx"
))
if
(
request_irq
(
config
->
irq
,
aic7xxx_isr
,
SA_INTERRUPT
,
"aic7xxx"
))
{
printk
(
"aic7xxx couldn't register irq %d, ignoring
\n
"
,
config
.
irq
);
aic7xxx_boards
[
config
.
irq
]
=
NULL
;
printk
(
"aic7xxx couldn't register irq %d, ignoring
\n
"
,
config
->
irq
);
aic7xxx_boards
[
config
->
irq
]
=
NULL
;
return
(
0
);
}
}
...
...
@@ -3663,8 +3953,8 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
* registered host adapter. Add this host adapter's Scsi_Host
* to the beginning of the linked list of hosts at the same IRQ.
*/
p
->
next
=
aic7xxx_boards
[
config
.
irq
];
aic7xxx_boards
[
config
.
irq
]
=
host
;
p
->
next
=
aic7xxx_boards
[
config
->
irq
];
aic7xxx_boards
[
config
->
irq
]
=
host
;
}
/*
...
...
@@ -3674,7 +3964,7 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
* but then your mailing address is dynamically assigned
* so no one can find you anyway :-)
*/
printk
(
"aic7xxx: Downloading sequencer code.."
);
printk
(
"aic7xxx: Downloading sequencer code..
.
"
);
aic7xxx_loadseq
(
base
);
/*
...
...
@@ -3690,27 +3980,37 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
printk
(
"done.
\n
"
);
/*
* Set the SCSI Id, SXFRCTL1, and SIMODE1, for both channels
* Set the SCSI Id, SXFRCTL
0, SXFRCTL
1, and SIMODE1, for both channels
*/
if
(
p
->
bus_type
==
AIC_TWIN
)
{
/*
* The device is gated to channel B after a chip reset,
* so set those values first.
* Select Channel B.
*/
outb
(
config
.
scsi_id_b
,
SCSIID
(
base
));
outb
((
sblkctl
&
~
SELBUS_MASK
)
|
SELBUSB
,
SBLKCTL
(
base
));
outb
(
config
->
scsi_id_b
,
SCSIID
(
base
));
scsi_conf
=
inb
(
HA_SCSICONF
(
base
)
+
1
)
&
(
ENSPCHK
|
STIMESEL
);
outb
(
scsi_conf
|
ENSTIMER
|
ACTNEGEN
|
STPWEN
,
SXFRCTL1
(
base
));
outb
(
ENSELTIMO
|
ENSCSIPERR
,
SIMODE1
(
base
));
if
(
p
->
ultra_enabled
)
{
outb
(
ULTRAEN
,
SXFRCTL0
(
base
));
}
/*
* Select Channel A
*/
outb
(
SELSINGLE
,
SBLKCTL
(
base
));
outb
(
(
sblkctl
&
~
SELBUS_MASK
)
|
SELSINGLE
,
SBLKCTL
(
base
));
}
outb
(
config
.
scsi_id
,
SCSIID
(
base
));
outb
(
config
->
scsi_id
,
SCSIID
(
base
));
scsi_conf
=
inb
(
HA_SCSICONF
(
base
))
&
(
ENSPCHK
|
STIMESEL
);
outb
(
scsi_conf
|
ENSTIMER
|
ACTNEGEN
|
STPWEN
,
SXFRCTL1
(
base
));
outb
(
ENSELTIMO
|
ENSCSIPERR
,
SIMODE1
(
base
));
if
(
p
->
ultra_enabled
)
{
outb
(
ULTRAEN
,
SXFRCTL0
(
base
));
}
/*
* Look at the information that board initialization or the board
...
...
@@ -3732,6 +4032,7 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
{
max_targets
=
16
;
}
/*
* Grab the disconnection disable table and invert it for our needs
*/
...
...
@@ -3749,7 +4050,8 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
}
else
{
p
->
discenable
=
~
(
inw
(
HA_DISC_DSB
(
base
)));
p
->
discenable
=
~
((
inb
(
HA_DISC_DSB
(
base
+
1
))
<<
8
)
|
inb
(
HA_DISC_DSB
(
base
)));
}
}
...
...
@@ -3807,7 +4109,7 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
* Clear the control byte for every SCB so that the sequencer
* doesn't get confused and think that one of them is valid
*/
for
(
i
=
0
;
i
<
config
.
maxscb
;
i
++
)
for
(
i
=
0
;
i
<
config
->
maxscb
;
i
++
)
{
outb
(
i
,
SCBPTR
(
base
));
outb
(
0
,
SCBARRAY
(
base
));
...
...
@@ -3817,7 +4119,7 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
* For reconnecting targets, the sequencer code needs to
* know how many SCBs it has to search through.
*/
outb
(
config
.
maxscb
,
HA_SCBCOUNT
(
base
));
outb
(
config
->
maxscb
,
HA_SCBCOUNT
(
base
));
/*
* Clear the active flags - no targets are busy.
...
...
@@ -3846,26 +4148,31 @@ aic7xxx_register(Scsi_Host_Template *template, aha_type type,
if
(
!
aic7xxx_no_reset
)
{
printk
(
"
Resetting the SCSI bus...
\n
"
);
printk
(
"
aic7xxx: Resetting the SCSI bus...
"
);
if
(
p
->
bus_type
==
AIC_TWIN
)
{
/*
* Select
c
hannel B.
* Select
C
hannel B.
*/
outb
(
SELBUSB
,
SBLKCTL
(
base
));
outb
((
sblkctl
&
~
SELBUS_MASK
)
|
SELBUSB
,
SBLKCTL
(
base
));
outb
(
SCSIRSTO
,
SCSISEQ
(
base
));
udelay
(
1000
);
outb
(
0
,
SCSISEQ
(
base
));
/*
* Select
c
hannel A.
* Select
C
hannel A.
*/
outb
(
SELSINGLE
,
SBLKCTL
(
base
));
outb
(
(
sblkctl
&
~
SELBUS_MASK
)
|
SELSINGLE
,
SBLKCTL
(
base
));
}
outb
(
SCSIRSTO
,
SCSISEQ
(
base
));
udelay
(
1000
);
outb
(
0
,
SCSISEQ
(
base
));
aic7xxx_delay
(
AIC7XXX_RESET_DELAY
);
printk
(
"done.
\n
"
);
}
/*
...
...
@@ -3891,8 +4198,10 @@ aic7xxx_detect(Scsi_Host_Template *template)
int
found
=
0
,
slot
,
base
;
unsigned
char
irq
=
0
;
int
i
;
struct
aic7xxx_host_config
config
;
template
->
proc_dir
=
&
proc_scsi_aic7xxx
;
config
.
chan_num
=
0
;
/*
* Since we may allow sharing of IRQs, it is imperative
...
...
@@ -3936,9 +4245,8 @@ aic7xxx_detect(Scsi_Host_Template *template)
aic7xxx_spurious_count
=
1
;
#if 0
printk("aic7xxx:
hcntrl=
0x%x\n", inb(HCNTRL(base)));
printk("aic7xxx:
HCNTRL:
0x%x\n", inb(HCNTRL(base)));
outb(inb(HCNTRL(base)) | CHIPRST, HCNTRL(base));
irq = inb(HA_INTDEF(base)) & 0x0F;
#endif
/*
...
...
@@ -3946,7 +4254,16 @@ aic7xxx_detect(Scsi_Host_Template *template)
* signature and we can set it up and register
* it with the kernel without incident.
*/
found
+=
aic7xxx_register
(
template
,
type
,
base
,
irq
);
config
.
type
=
type
;
config
.
base
=
base
;
config
.
irq
=
irq
;
config
.
parity
=
AIC_UNKNOWN
;
config
.
low_term
=
AIC_UNKNOWN
;
config
.
high_term
=
AIC_UNKNOWN
;
config
.
busrtime
=
0
;
config
.
walk_scbs
=
FALSE
;
config
.
ultra_enabled
=
FALSE
;
found
+=
aic7xxx_register
(
template
,
&
config
);
/*
* Disallow spurious interrupts.
...
...
@@ -3957,11 +4274,6 @@ aic7xxx_detect(Scsi_Host_Template *template)
#ifdef CONFIG_PCI
#define DEVREVID 0x08
#define DEVCONFIG 0x40
#define DEVSTATUS 0x41
#define RAMPSM 0x02
/*
* PCI-bus probe.
*/
...
...
@@ -4001,6 +4313,27 @@ aic7xxx_detect(Scsi_Host_Template *template)
index
,
&
pci_bus
,
&
pci_device_fn
))
{
type
=
AIC_7872
;
config
.
chan_num
=
number_of_3940s
&
0x1
;
number_of_3940s
++
;
}
else
{
if
((
!
pcibios_find_device
(
PCI_VENDOR_ID_ADAPTEC
,
PCI_DEVICE_ID_ADAPTEC_7881
,
index
,
&
pci_bus
,
&
pci_device_fn
))
||
(
!
pcibios_find_device
(
PCI_VENDOR_ID_ADAPTEC
,
PCI_DEVICE_ID_ADAPTEC_7880
,
index
,
&
pci_bus
,
&
pci_device_fn
)))
{
type
=
AIC_7880
;
}
else
{
if
(
!
pcibios_find_device
(
PCI_VENDOR_ID_ADAPTEC
,
PCI_DEVICE_ID_ADAPTEC_7882
,
index
,
&
pci_bus
,
&
pci_device_fn
))
{
type
=
AIC_7882
;
}
else
{
...
...
@@ -4009,6 +4342,8 @@ aic7xxx_detect(Scsi_Host_Template *template)
}
}
}
}
}
if
(
!
done
)
{
...
...
@@ -4017,7 +4352,6 @@ aic7xxx_detect(Scsi_Host_Template *template)
*/
error
=
pcibios_read_config_dword
(
pci_bus
,
pci_device_fn
,
PCI_BASE_ADDRESS_0
,
&
io_port
);
if
(
error
)
{
panic
(
"aic7xxx_detect: error 0x%x reading i/o port.
\n
"
,
error
);
...
...
@@ -4030,42 +4364,62 @@ aic7xxx_detect(Scsi_Host_Template *template)
panic
(
"aic7xxx_detect: error %d reading irq.
\n
"
,
error
);
}
/*
* Make the base I/O register look like EISA and VL-bus.
*/
base
=
io_port
-
0xC01
;
/*
* I don't think we need to bother with allowing
* spurious interrupts for the 787x/7850, but what
* the hey.
*/
aic7xxx_spurious_count
=
1
;
#if 0
printk("aic7xxx: hcntrl=0x%x\n", inb(HCNTRL(base)));
#endif
outb
(
inb
(
HCNTRL
(
base
))
|
CHIPRST
,
HCNTRL
(
base
));
error
=
pcibios_read_config_byte
(
pci_bus
,
pci_device_fn
,
DEVREVID
,
&
devrevid
);
if
(
error
)
{
panic
(
"aic7xxx_detect: error %d reading device revision id.
\n
"
,
error
);
}
if
(
devrevid
<
3
)
{
printk
(
"aic7xxx_detect: AIC-7870 Rev %c
\n
"
,
rev_id
[
devrevid
]);
}
error
=
pcibios_read_config_byte
(
pci_bus
,
pci_device_fn
,
DEVCONFIG
,
&
devconfig
);
if
(
error
)
{
panic
(
"aic7xxx_detect: error %d reading device configuration.
\n
"
,
error
);
}
error
=
pcibios_read_config_byte
(
pci_bus
,
pci_device_fn
,
DEVSTATUS
,
&
devstatus
);
if
(
error
)
{
panic
(
"aic7xxx_detect: error %d reading device status.
\n
"
,
error
);
}
printk
(
"aic7xxx_detect: devconfig 0x%x, devstatus 0x%x
\n
"
,
devconfig
,
devstatus
);
if
(
devstatus
&
RAMPSM
)
/*
* Make the base I/O register look like EISA and VL-bus.
*/
base
=
io_port
-
0xC01
;
/*
* I don't think we need to bother with allowing
* spurious interrupts for the 787x/7850, but what
* the hey.
*/
aic7xxx_spurious_count
=
1
;
config
.
type
=
type
;
config
.
base
=
base
;
config
.
irq
=
irq
;
config
.
parity
=
AIC_UNKNOWN
;
config
.
low_term
=
AIC_UNKNOWN
;
config
.
high_term
=
AIC_UNKNOWN
;
config
.
busrtime
=
0
;
config
.
walk_scbs
=
FALSE
;
config
.
ultra_enabled
=
FALSE
;
if
((
devstatus
&
RAMPSM
)
||
(
devconfig
&
SCBRAMSEL
)
||
(
type
==
AIC_7872
))
{
printk
(
"aic7xxx_detect: detected external SCB RAM, "
"mail deang@ims.com for test patch"
);
config
.
walk_scbs
=
TRUE
;
}
found
+=
aic7xxx_register
(
template
,
type
,
base
,
irq
);
found
+=
aic7xxx_register
(
template
,
&
config
);
/*
* Disable spurious interrupts.
...
...
@@ -4530,8 +4884,24 @@ aic7xxx_abort(Scsi_Cmnd *cmd)
save_flags
(
flags
);
cli
();
if
(
scb
->
state
&
SCB_ACTIVE
)
{
if
(
scb
->
state
&
SCB_IMMED
)
{
/*
* Don't know how set the number of retries to 0.
*/
/* cmd->retries = 0; */
aic7xxx_done
(
p
,
scb
);
}
else
{
/*
* Abort the operation.
*/
aic7xxx_abort_scb
(
p
,
scb
);
}
}
restore_flags
(
flags
);
return
(
0
);
}
...
...
drivers/scsi/aic7xxx.seq
View file @
a89a2558
...
...
@@ -25,13 +25,14 @@
# optimizations provided by Justin T. Gibbs (gibbs@FreeBSD.org)
##-M#########################################################################
VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 2.
1 1995/08/30 07:47:07
deang Exp $"
VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 2.
3 1995/11/10 10:51:22
deang Exp $"
SCBMASK = 0xff
SCSISEQ = 0x00
ENRSELI = 0x10
SXFRCTL0 = 0x01
ULTRAEN = 0x20
SXFRCTL1 = 0x02
SCSISIGI = 0x03
SCSISIGO = 0x03
...
...
@@ -229,7 +230,6 @@ ACTIVE_B = 0x55
SAVED_TCL = 0x56 # Temporary storage for the
# target/channel/lun of a
# reconnecting target
# After starting the selection hardware, we return to the "poll_for_work"
# loop so that we can check for reconnecting targets as well as for our
# selection to complete just in case the reselection wins bus arbitration.
...
...
@@ -444,6 +444,7 @@ ITloop:
and A,0xe0,SCSISIGI # CDI|IOI|MSGI
mov A call scsisig
cmp ALLZEROS,A je p_dataout
cmp A,0x40 je p_datain
cmp A,0x80 je p_command
...
...
@@ -454,7 +455,6 @@ ITloop:
mvi INTSTAT,BAD_PHASE # unknown - signal driver
p_dataout:
mvi 0 call scsisig # !CDO|!IOO|!MSGO
mvi DMAPARAMS,0x7d # WIDEODD|SCSIEN|SDMAEN|HDMAEN|
# DIRECTION|FIFORESET
jmp data_phase_init
...
...
@@ -469,8 +469,7 @@ data_phase_reinit:
# Reads should not use WIDEODD since it may make the last byte for a SG segment
# go to the next segment.
p_datain:
mvi 0x40 call scsisig # !CDO|IOO|!MSGO
mvi DMAPARAMS,0x39 # SCSIEN|SDMAEN|HDMAEN|
mvi DMAPARAMS,0x79 # WIDEODD|SCSIEN|SDMAEN|HDMAEN|
# !DIRECTION|FIFORESET
data_phase_init:
call assert
...
...
@@ -574,7 +573,6 @@ data_phase_finish:
# so we can copy those three bytes directly into HCNT.
#
p_command:
mvi 0x80 call scsisig # CDO|!IOO|!MSGO
call assert
# Load HADDR and HCNT. We can do this in one bcopy since they are neighbors
...
...
@@ -592,7 +590,6 @@ p_command:
# and store it into the SCB.
#
p_status:
mvi 0xc0 call scsisig # CDO|IOO|!MSGO
mvi SCBARRAY+14 call inb_first
jmp mesgin_done
...
...
@@ -601,7 +598,6 @@ p_status:
# took us into this phase anyway, build a no-op message and send it.
#
p_mesgout:
mvi 0xa0 call scsisig # CDO|!IOO|MSGO
mvi 0x8 call mk_mesg # build NOP message
clr STCNT+2
...
...
@@ -661,7 +657,8 @@ p_mesgout5:
and A,0xe0,SCSISIGI # CDI|IOI|MSGI
cmp A,0xa0 jne p_mesgout6
mvi 0x10 call scsisig # ATNO - re-assert ATN
or SINDEX,0x10,SIGSTATE # turn on ATNO
call scsisig # ATNO - re-assert ATN
jmp ITloop
...
...
@@ -679,7 +676,6 @@ p_mesgout6:
# to a data I/O phase.
#
p_mesgin:
mvi 0xe0 call scsisig # CDO|IOO|MSGO
mvi A call inb_first # read the 1st message byte
mvi REJBYTE,A # save it for the driver
...
...
@@ -742,11 +738,12 @@ status_ok:
mov A,FUNCTION1
test SCBARRAY+1,0x88 jz clear_a
xor ACTIVE_B,A
jmp
comple
te
jmp
immedia
te
clear_a:
xor ACTIVE_A,A
immediate:
test SCBARRAY+11,0xff jnz complete # Immediate message complete
# Pause the sequencer until the driver gets around to handling the command
# complete. This is so that any action that might require carefull timing
...
...
@@ -1011,7 +1008,8 @@ dma4:
# actually off first lest we get an ILLSADDR.
#
dma5:
clr DFCNTRL # disable DMA
and DFCNTRL, 0x40, SINDEX # disable DMA, but maintain
# WIDEODD
dma6:
test DFCNTRL,0x38 jnz dma6 # SCSIENACK|SDMAENACK|HDMAENACK
...
...
@@ -1044,7 +1042,7 @@ initialize_for_target:
#
clr SIGSTATE
mvi
SXFRCTL0,0x8a # DFON|SPIOEN|CLRCHN
or
SXFRCTL0,0x8a # DFON|SPIOEN|CLRCHN
# Make sure that the system knows we have not been through a DATA
# phase.
...
...
@@ -1205,7 +1203,8 @@ sdtr_to_rate_loop:
jmp sdtr_to_rate_loop
sdtr_to_rate_done:
shr RETURN_1,0x2
add RETURN_1,0x18 ret
add RETURN_1,0x18
test SXFRCTL0,ULTRAEN jz return
shr RETURN_1,0x1
return:
ret
drivers/scsi/scsi.c
View file @
a89a2558
...
...
@@ -796,6 +796,7 @@ static void scsi_times_out (Scsi_Cmnd * SCpnt, int pid)
*/
printk
(
"Unable to reset scsi host %d - "
,
SCpnt
->
host
->
host_no
);
printk
(
"probably a SCSI bus hang.
\n
"
);
SCpnt
->
internal_timeout
&=
~
IN_RESET
;
scsi_reset
(
SCpnt
,
TRUE
);
return
;
...
...
@@ -1834,6 +1835,26 @@ int scsi_abort (Scsi_Cmnd * SCpnt, int why, int pid)
}
}
/* Mark a single SCSI Device as having been reset. */
static
inline
void
scsi_mark_device_reset
(
Scsi_Device
*
Device
)
{
Device
->
was_reset
=
1
;
Device
->
expecting_cc_ua
=
1
;
}
/* Mark all SCSI Devices on a specific Host as having been reset. */
void
scsi_mark_host_bus_reset
(
struct
Scsi_Host
*
Host
)
{
Scsi_Cmnd
*
SCpnt
;
for
(
SCpnt
=
Host
->
host_queue
;
SCpnt
;
SCpnt
=
SCpnt
->
next
)
scsi_mark_device_reset
(
SCpnt
->
device
);
}
int
scsi_reset
(
Scsi_Cmnd
*
SCpnt
,
int
bus_reset_flag
)
{
int
temp
,
oldto
;
...
...
@@ -1935,27 +1956,20 @@ int scsi_reset (Scsi_Cmnd * SCpnt, int bus_reset_flag)
printk
(
"scsi reset function returned %d
\n
"
,
temp
);
#endif
if
(
temp
&
SCSI_RESET_BUS_RESET
)
{
/*
* The low level driver did a bus reset, so we should
* go through and mark all of the devices on that bus
* as having been reset.
*/
SCpnt1
=
host
->
host_queue
;
while
(
SCpnt1
)
{
SCpnt1
->
device
->
was_reset
=
1
;
SCpnt1
->
device
->
expecting_cc_ua
=
1
;
SCpnt1
=
SCpnt1
->
next
;
}
}
/*
* Now figure out what we need to do, based upon
* what the low level driver said that it did.
* If the result is SCSI_RESET_SUCCESS, SCSI_RESET_PENDING,
* or SCSI_RESET_WAKEUP, then the low level driver did a
* bus device reset or bus reset, so we should go through
* and mark one or all of the devices on that bus
* as having been reset.
*/
switch
(
temp
&
SCSI_RESET_ACTION
)
{
case
SCSI_RESET_SUCCESS
:
if
(
temp
&
SCSI_RESET_BUS_RESET
)
scsi_mark_host_bus_reset
(
host
);
else
scsi_mark_device_reset
(
SCpnt
->
device
);
save_flags
(
flags
);
cli
();
SCpnt
->
internal_timeout
&=
~
IN_RESET
;
...
...
@@ -1963,12 +1977,18 @@ int scsi_reset (Scsi_Cmnd * SCpnt, int bus_reset_flag)
restore_flags
(
flags
);
return
0
;
case
SCSI_RESET_PENDING
:
if
(
temp
&
SCSI_RESET_BUS_RESET
)
scsi_mark_host_bus_reset
(
host
);
else
scsi_mark_device_reset
(
SCpnt
->
device
);
return
0
;
case
SCSI_RESET_PUNT
:
SCpnt
->
internal_timeout
&=
~
IN_RESET
;
scsi_request_sense
(
SCpnt
);
return
0
;
case
SCSI_RESET_WAKEUP
:
if
(
temp
&
SCSI_RESET_BUS_RESET
)
scsi_mark_host_bus_reset
(
host
);
else
scsi_mark_device_reset
(
SCpnt
->
device
);
SCpnt
->
internal_timeout
&=
~
IN_RESET
;
scsi_request_sense
(
SCpnt
);
/*
...
...
drivers/scsi/scsi.h
View file @
a89a2558
...
...
@@ -449,6 +449,7 @@ extern void proc_print_scsidevice(Scsi_Device *, char *, int *, int);
extern
void
print_command
(
unsigned
char
*
);
extern
void
print_sense
(
const
char
*
,
Scsi_Cmnd
*
);
extern
void
scsi_mark_host_bus_reset
(
struct
Scsi_Host
*
Host
);
#if defined(MAJOR_NR) && (MAJOR_NR != SCSI_TAPE_MAJOR)
#include "hosts.h"
...
...
drivers/scsi/sd.c
View file @
a89a2558
...
...
@@ -1134,6 +1134,12 @@ static int sd_init_onedisk(int i)
rscsi_disks
[
i
].
sector_size
=
(
buffer
[
4
]
<<
24
)
|
(
buffer
[
5
]
<<
16
)
|
(
buffer
[
6
]
<<
8
)
|
buffer
[
7
];
if
(
rscsi_disks
[
i
].
sector_size
==
0
)
{
rscsi_disks
[
i
].
sector_size
=
512
;
printk
(
"sd%c : sector size 0 reported, assuming 512.
\n
"
,
'a'
+
i
);
}
if
(
rscsi_disks
[
i
].
sector_size
!=
512
&&
rscsi_disks
[
i
].
sector_size
!=
1024
&&
rscsi_disks
[
i
].
sector_size
!=
256
)
...
...
fs/ext2/super.c
View file @
a89a2558
...
...
@@ -157,9 +157,9 @@ static int parse_options (char * options, unsigned long * sb_block,
clear_opt
(
*
mount_options
,
CHECK_NORMAL
);
clear_opt
(
*
mount_options
,
CHECK_STRICT
);
}
else
if
(
strcmp
(
value
,
"normal"
))
else
if
(
!
strcmp
(
value
,
"normal"
))
set_opt
(
*
mount_options
,
CHECK_NORMAL
);
else
if
(
strcmp
(
value
,
"strict"
))
{
else
if
(
!
strcmp
(
value
,
"strict"
))
{
set_opt
(
*
mount_options
,
CHECK_NORMAL
);
set_opt
(
*
mount_options
,
CHECK_STRICT
);
}
...
...
fs/msdos/inode.c
View file @
a89a2558
...
...
@@ -81,7 +81,7 @@ static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
*
check
=
'n'
;
*
conversion
=
'b'
;
*
dotsOK
=
1
;
*
dotsOK
=
0
;
*
uid
=
current
->
uid
;
*
gid
=
current
->
gid
;
*
umask
=
current
->
fs
->
umask
;
...
...
include/asm-alpha/system.h
View file @
a89a2558
...
...
@@ -100,37 +100,39 @@ __old_ipl; })
/*
* Give prototypes to shut up gcc.
*/
extern
inline
unsigned
long
xchg_u32
(
volatile
int
*
m
,
unsigned
long
new_
val
);
extern
inline
unsigned
long
xchg_u64
(
volatile
long
*
m
,
unsigned
long
new_
val
);
extern
inline
unsigned
long
xchg_u32
(
volatile
int
*
m
,
unsigned
long
val
);
extern
inline
unsigned
long
xchg_u64
(
volatile
long
*
m
,
unsigned
long
val
);
extern
inline
unsigned
long
xchg_u32
(
volatile
int
*
m
,
unsigned
long
new_
val
)
extern
inline
unsigned
long
xchg_u32
(
volatile
int
*
m
,
unsigned
long
val
)
{
unsigned
long
old_val
;
__asm__
__volatile__
(
"
\n
1:
\t
"
"ldl_l %0,%2
\n\t
"
"bis %3,%3,$25
\n\t
"
"stl_c $25,%1
\n\t
"
"beq $25,1b
\n
"
:
"=r"
(
old_val
),
"=m"
(
*
m
)
:
"m"
(
*
m
),
"r"
(
new_val
)
:
"$25"
);
return
old_val
;
unsigned
long
dummy
,
dummy2
;
__asm__
__volatile__
(
"
\n
1:
\t
"
"ldl_l %0,0(%1)
\n\t
"
"bis %2,%2,%3
\n\t
"
"stl_c %3,0(%1)
\n\t
"
"beq %3,1b
\n
"
:
"=r"
(
val
),
"=r"
(
m
),
"=r"
(
dummy
),
"=r"
(
dummy2
)
:
"1"
(
m
),
"2"
(
val
)
:
"memory"
);
return
val
;
}
extern
inline
unsigned
long
xchg_u64
(
volatile
long
*
m
,
unsigned
long
new_
val
)
extern
inline
unsigned
long
xchg_u64
(
volatile
long
*
m
,
unsigned
long
val
)
{
unsigned
long
old_val
;
__asm__
__volatile__
(
"
\n
1:
\t
"
"ldq_l %0,%2
\n\t
"
"bis %3,%3,$25
\n\t
"
"stq_c $25,%1
\n\t
"
"beq $25,1b
\n
"
:
"=r"
(
old_val
),
"=m"
(
*
m
)
:
"m"
(
*
m
),
"r"
(
new_val
)
:
"$25"
);
return
old_val
;
unsigned
long
dummy
,
dummy2
;
__asm__
__volatile__
(
"
\n
1:
\t
"
"ldq_l %0,0(%1)
\n\t
"
"bis %2,%2,%3
\n\t
"
"stq_c %3,0(%1)
\n\t
"
"beq %3,1b
\n
"
:
"=r"
(
val
),
"=r"
(
m
),
"=r"
(
dummy
),
"=r"
(
dummy2
)
:
"1"
(
m
),
"2"
(
val
)
:
"memory"
);
return
val
;
}
#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
...
...
include/asm-i386/ioctl.h
View file @
a89a2558
...
...
@@ -6,8 +6,6 @@
#ifndef _ASMI386_IOCTL_H
#define _ASMI386_IOCTL_H
#include <asm/page.h>
/* for PAGE_SIZE */
/* ioctl command encoding: 32 bits total, command in lower 16 bits,
* size of the parameter structure in the lower 14 bits of the
* upper 16 bits.
...
...
@@ -18,38 +16,6 @@
* NOTE: This limits the max parameter size to 16kB -1 !
*/
#define IOC_VOID 0x00000000
/* param in size field */
#define IOC_IN 0x40000000
/* user --> kernel */
#define IOC_OUT 0x80000000
/* kernel --> user */
#define IOC_INOUT (IOC_IN | IOC_OUT)
/* both */
#define IOCSIZE_MASK 0x3fff0000
/* size (max 16k-1 bytes) */
#define IOCSIZE_SHIFT 16
/* how to get the size */
#define IOCSIZE_MAX ((PAGE_SIZE-1)&(IOCSIZE_MASK >> IOCSIZE_SHIFT))
#define IOCCMD_MASK 0x0000ffff
/* command code */
#define IOCCMD_SHIFT 0
#define IOCPARM_MASK IOCCMD_MASK
#define IOCPARM_SHIFT IOCCMD_SHIFT
#define IOC_SIZE(cmd) (((cmd) & IOCSIZE_MASK) >> IOCSIZE_SHIFT)
#define IOCBASECMD(cmd) ((cmd) & ~IOCPARM_MASK)
#define IOCGROUP(cmd) (((cmd) >> 8) & 0xFF)
/* _IO(magic, subcode); size field is zero and the
* subcode determines the command.
*/
#define _IO(c,d) (IOC_VOID | ((c)<<8) | (d))
/* param encoded */
/* _IOXX(magic, subcode, arg_t); where arg_t is the type of the
* (last) argument field in the ioctl call, if present.
*/
#define _IOW(c,d,t) (IOC_IN | ((sizeof(t)<<16) & IOCSIZE_MASK) | \
((c)<<8) | (d))
#define _IOR(c,d,t) (IOC_OUT | ((sizeof(t)<<16) & IOCSIZE_MASK) | \
((c)<<8) | (d))
/* WR rather than RW to avoid conflict with stdio.h */
#define _IOWR(c,d,t) (IOC_INOUT | ((sizeof(t)<<16) & IOCSIZE_MASK) | \
((c)<<8) | (d))
/*
* The following is for compatibility across the various Linux
* platforms. The i386 ioctl numbering scheme doesn't really enforce
...
...
@@ -80,10 +46,30 @@
#define _IOC_READ 1U
#define _IOC_WRITE 2U
#define _IOC(dir,type,nr,size) \
(((dir) << _IOC_DIRSHIFT) | \
((type) << _IOC_TYPESHIFT) | \
((nr) << _IOC_NRSHIFT) | \
((size) << _IOC_SIZESHIFT))
/* used to create numbers */
#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
/* used to decode ioctl numbers.. */
#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
/* ...and for the drivers/sound files... */
#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
#endif
/* _ASMI386_IOCTL_H */
include/asm-i386/irq.h
View file @
a89a2558
...
...
@@ -127,7 +127,7 @@ extern void enable_irq(unsigned int);
#define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr)
#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
#ifdef __
_
SMP__
#ifdef __SMP__
#define GET_PROCESSOR_ID \
"movl "SYMBOL_NAME_STR(apic_reg)", %edx\n\t" \
...
...
include/linux/mcd.h
View file @
a89a2558
...
...
@@ -110,8 +110,7 @@ struct mcd_Toc {
struct
msf
diskTime
;
};
#if 0
#ifndef I_WAS_HERE
#
error Please edit this file first.
#
endif
#
warning You have not edited mcd.h
#
warning Perhaps irq and i/o settings are wrong.
#endif
include/linux/mcdx.h
View file @
a89a2558
/*
* Definitions for the Mitsumi CDROM interface
* Copyright (C) 1995 Heiko Schlittermann
* VERSION: 1.
0a
* Copyright (C) 1995 Heiko Schlittermann
<heiko@lotte.sax.de>
* VERSION: 1.
3
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
...
...
@@ -92,10 +92,16 @@
#define INIT 0
#define MALLOC 0
#define IOCTL 0
#define PLAYTRK 0
#define SUBCHNL 0
#define TOCHDR 0
#define MS 0
#define PLAYMSF 0
#define READTOC 0
#define OPENCLOSE 0
#define HW 0
#define TALK 0
#define IRQ
0
#define IRQ
1
#define TRANSFER 0
#define REQUEST 0
#else
...
...
@@ -173,8 +179,7 @@
#define MCDX_E 1
/* unspec error */
#define MCDX_EOM 2
/* end of media */
#if 0
#ifndef I_WAS_HERE
#
error Please edit this file first.
#
endif
#
warning You have not edited mcdx.h
#
warning Perhaps irq and i/o settings are wrong.
#endif
include/linux/pci.h
View file @
a89a2558
...
...
@@ -454,6 +454,7 @@
#define PCI_DEVICE_ID_ADAPTEC_7872 0x7278
#define PCI_DEVICE_ID_ADAPTEC_7880 0x8078
#define PCI_DEVICE_ID_ADAPTEC_7881 0x8178
#define PCI_DEVICE_ID_ADAPTEC_7882 0x8278
#define PCI_VENDOR_ID_ATRONICS 0x907f
#define PCI_DEVICE_ID_ATRONICS_2015 0x2015
...
...
include/linux/tty.h
View file @
a89a2558
...
...
@@ -328,6 +328,7 @@ extern int pty_open(struct tty_struct * tty, struct file * filp);
extern
int
con_open
(
struct
tty_struct
*
tty
,
struct
file
*
filp
);
extern
void
update_screen
(
int
new_console
);
extern
void
console_print
(
const
char
*
);
/* vt.c */
...
...
kernel/ksyms.c
View file @
a89a2558
...
...
@@ -266,6 +266,8 @@ struct symbol_table symbol_table = {
X
(
tty_wait_until_sent
),
X
(
tty_check_change
),
X
(
tty_hung_up_p
),
X
(
do_SAK
),
X
(
console_print
),
/* filesystem registration */
X
(
register_filesystem
),
...
...
net/ipv4/proc.c
View file @
a89a2558
...
...
@@ -111,8 +111,8 @@ get__netinfo(struct proto *pro, char *buffer, int format, char **start, off_t of
}
len
+=
sprintf
(
buffer
+
len
,
"%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d %d
\n
"
,
i
,
src
,
srcp
,
dest
,
destp
,
sp
->
state
,
format
==
0
?
sp
->
write_seq
-
sp
->
rcv_ack_seq
:
sp
->
r
mem_alloc
,
format
==
0
?
sp
->
acked_seq
-
sp
->
copied_seq
:
sp
->
w
mem_alloc
,
format
==
0
?
sp
->
write_seq
-
sp
->
rcv_ack_seq
:
sp
->
w
mem_alloc
,
format
==
0
?
sp
->
acked_seq
-
sp
->
copied_seq
:
sp
->
r
mem_alloc
,
timer_active
,
timer_expires
-
jiffies
,
(
unsigned
)
sp
->
retransmits
,
(
sp
->
socket
&&
SOCK_INODE
(
sp
->
socket
))
?
SOCK_INODE
(
sp
->
socket
)
->
i_uid
:
0
,
timer_active
?
sp
->
timeout
:
0
);
...
...
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