S: France
N: Rik van Riel
-E: H.H.vanRiel@phys.uu.nl
-W: http://www.phys.uu.nl/~riel/
+E: H.H.vanRiel@humbolt.geo.uu.nl
+W: http://humbolt.geo.uu.nl/
D: Maintainer of the mm-patches page (see www.linuxhq.com)
D: Documentation/sysctl/*, kswapd fixes, random kernel hacker
S: Vorenkampsweg 1
E: rubini@ipvvis.unipv.it
D: the gpm mouse server and kernel support for it
+N: Philipp Rumpf
+E: prumpf@jcsbs.lanobis.de
+D: ipi_count for x86
+D: random bugfixes
+S: Rueting 4
+S: 23743 Groemitz
+S: Germany
+
N: Paul Russell
E: Paul.Russell@rustcorp.com.au
W: http://www.rustcorp.com
S: San Jose, California
S: USA
+N: Jaspreet Singh
+E: jaspreet@sangoma.com
+W: www.sangoma.com
+D: WANPIPE driver for Sangoma S508/FT1 cards
+S: Sangoma Technologies Inc.,
+S: 1001 Denison Street
+S: Suite 101
+S: Markham, Ontario L3R 2Z6
+S: Canada
+
N: Rick Sladkey
E: jrs@world.std.com
D: utility hacker: Emacs, NFS server, mount, kmem-ps, UPS debugger, strace, GDB
This driver:
- o handles XA (and hopefully) multi session CDs as well as
+ o handles XA and (hopefully) multi session CDs as well as
ordinary CDs;
o supports up to 5 drives (of course, you'll need free
IRQs, i/o ports and slots);
o uses much less kernel memory than the standard mcd driver
(no extra driver internal buffers!).
- o plays audio (like the `old' driver, I hope)
+ o plays audio (like the `old' driver, I hope)
This version doesn't support yet:
In case you have problems with this version (1.6.1) of this driver, please
email directly to me as I made the last update. It you have a report about
-runnning it on other architectures than intel, email me, so I can document
+running it on other architectures than intel, email me, so I can document
it here.
A version of this driver has been taken by Digiboard to make a driver
drivers started device names with 1.
PCI boards are auto-detected and configured by the driver. PCI boards will
-be allocated device numbers (internally) begining with the lowest PCI slot
+be allocated device numbers (internally) beginning with the lowest PCI slot
first. In other words a PCI card in slot 3 will always have higher device
nodes than a PCI card in slot 1.
Base of memory window (in HEX if using string identifiers),
NOTE : PCI boards are auto-detected and configured. Do not attempt to
-configure PCI boards with the LILO append comand. If you wish to override
+configure PCI boards with the LILO append command. If you wish to override
previous configuration data (As set by digiConfig), but you do not wish to
configure any specific card (Example if there are PCI cards in the system)
the following override command will accomplish this:
noinit - tells driver, that devices were already initialized. You should use it
if you have G100 and/or if driver cannot detect memory, you see strange
pattern on screen and so on. Devices not enabled by BIOS are still
- initialized.
-init - driver initializes every device it knows about. It is default.
+ initialized. It is default.
+init - driver initializes every device it knows about.
+nomtrr - disables write combining on frame buffer. This slows down driver but
+ there is reported minor incompatibility between GUS DMA and XFree under
+ high loads if write combining is enabled (sound dropouts).
+mtrr - enables write combining on frame buffer. It speeds up video accesses
+ much. It is default. You must have MTRR support enabled in kernel and
+ your CPU must have MTRR (f.e. Pentium II have them).
+sgram - tells to driver that you have G200 with SGRAM memory. It has no effect
+ without `init'.
+sdram - tells to driver that you have G200 with SDRAM memory. It is a default.
inv24 - change timings parameters for 24bpp modes on Millenium and Millenium II.
Specify this if you see strange color shadows around characters.
noinv24 - use standard timmings. It is default.
+ 24bpp does not support correctly XF-FBDev on big-endian architectures.
+ interlaced text mode is not supported; it looks like hardware limitiation,
but I'm not sure.
+ + G200 SGRAM/SDRAM is not autodetected.
+ maybe more...
And following misfeatures:
+ SVGALib does not restore screen on exit.
Version. Currently, only the ISA-Bus version of the card is supported.
However MCA and PCMCIA will follow soon.
-The ISA-Bus Version uses 8 IO-ports. The base port adress has to be set
+The ISA-Bus Version uses 8 IO-ports. The base port address has to be set
manually using the DIP switches.
Setting up the DIP switches for the IBM Active 2000 ISDN card:
then the interface of the service function could be changed
by passing a pointer of type (struct device*) instead of
type (struct concap_proto*). Doing so would make many of the service
-functions compatible to network device support fuctions.
+functions compatible to network device support functions.
e.g. instead of the concap protocol's service function
As this is compatible to the dev->hard_start_xmit() method, the device
driver could directly register the concap protocol's encap_and_xmit()
-fuction as its hard_start_xmit() method. This would eliminate one
+function as its hard_start_xmit() method. This would eliminate one
procedure call layer.
isdnloop driver. It seems that it is not caused by the isdn code.
Somehow, the inode of a socket is freed while a process still refers
the socket's wait queue. This causes problems when the process tries to
-remove itself from the wait queue (refered by the dangling
+remove itself from the wait queue (referred by the dangling
sock->sleep pointer) before returning from a select() system call.
- Henner
I wanted the two lock styles to be cooperative, but there were so many
race and deadlock conditions that the current solution was the only
practical one. It puts us in the same position as, for example, SunOS
-4.1.x and serveral other commercial Unices. The only OS's that support
+4.1.x and several other commercial Unices. The only OS's that support
cooperative flock()/fcntl() are those that emulate flock() using
fcntl(), with all the problems that implies.
Legal values are between 0 and 255. Default: 255/0. Note: This
value is forced to 0 on a Falcon, since scatter-gather isn't
possible with the ST-DMA. Not using scatter-gather hurts
- perfomance significantly.
+ performance significantly.
<host-id>:
The SCSI ID to be used by the initiator (your Atari). This is
- The PC is given full control over the radio
channel. Special control data is exchanged between the PC and the TNC so
that the PC knows at any time if the TNC is receiving data, if a TNC
- buffer underrun or overrun has occured, if the PTT is
+ buffer underrun or overrun has occurred, if the PTT is
set and so on. This control data is processed at a higher priority than
normal data, so a data stream can be interrupted at any time to issue an
important event. This helps to improve the channel access and timing
some cleaning and optimizing. This will be done in a later release.
If you encounter a bug or if you have a question or suggestion concerning the
-driver, feel free to mail me, using the adresses given at the beginning of
+driver, feel free to mail me, using the addresses given at the beginning of
this file.
Have fun!
--------------------
The two jumpers labeled ET1 and ET2 are used to determine the timeout
-parameters (respons and reconfiguration time). Every node in a network
+parameters (response and reconfiguration time). Every node in a network
must be set to the same timeout values.
ET1 ET2 | Response Time (us) | Reconfiguration Time (ms)
DAYNA driver mode:
Dayna DL2000/DaynaTalk PC (Half Length), COPS LT-95,
Farallon PhoneNET PC III, Farallon PhoneNET PC II
-Other cards possibly supported mode unkown though:
+Other cards possibly supported mode unknown though:
Dayna DL2000 (Full length)
The COPS driver defaults to using Dayna mode. To change the driver's
autonegotiation feature in the SROM autoconf code, this detection will
occur automatically for that case.
- Command line arguements are now allowed, similar to passing arguements
+ Command line arguments are now allowed, similar to passing arguments
through LILO. This will allow a per adapter board set up of full duplex
and media. The only lexical constraints are: the board name (dev->name)
appears in the list before its parameters. The list of parameters ends
ad1848 are the corresponding options for the MSS and OPL3 modules.
Loading MSS and OPL3 needs to pre load the aedsp16 module to set up correctly
-the sound card. Installation dependancies must be written in the conf.modules
+the sound card. Installation dependencies must be written in the conf.modules
file:
pre-install ad1848 modprobe aedsp16
---------------------------------------------------------------
Scott Murray, scottm@interlog.com
-December, 1998
+January 5, 1998
NOTE: All trade-marked terms mentioned below are properties of their
respective owners.
If you still cannot get the module to load, look at the contents of
your system log file, usually /var/log/messages. If you see the
-message "No Yamaha audio controller found", then you have a different
-chipset than I've encountered so far. Look for a line in the log file
-that says "opl3sa2.c: chipset version = <some number>". If you want
-me to add support for your card, send me the number from this line and
-any information you have on the make and chipset of your sound card,
-and I should be able to work up a permanent fix.
-
-A temporary solution is to force the driver to act as either a SA2 or
-SA3. If you use the modular driver, this can be done with the "force"
-option. Using "force=2" makes the driver treat your card as a SA2,
-and "force=3" makes it treat your card as a SA3. Note that the driver
-does not really differentiate internally between the SA3 and SAx, so
-"force=3" is actually suitable for an SAx card.
-
-If you build the driver into the kernel, a similar option is
-available, "Chipset". Setting it to 2 or 3 will yield the same result
-as the "force" option does for the module. I recommend trying
-auto-probing first ("Chipset" equal to the default of -1) before
-forcing compatibility with a specific chipset.
+message "Unknown Yamaha audio controller version", then you have a
+different chipset than I've encountered so far. Look for a line in
+the log file that says "opl3sa2.c: chipset version = <some number>".
+If you want me to add support for your card, send me the number from
+this line and any information you have on the make and chipset of your
+sound card, and I should be able to work up a permanent fix.
If you do not see the chipset version message, and none of the other
messages present in the system log are helpful, email me some details
--- /dev/null
+Running sound cards on VIA chipsets
+
+o There are problems with VIA chipsets and sound cards that appear to
+ lock the hardware solidly. Test programs under DOS have verified the
+ problem exists on at least some (but apparently not all) VIA boards
+
+o VIA have so far failed to bother to answer support mail on the subject
+ so if you are a VIA engineer feeling aggrieved as you read this
+ document go chase your own people. If there is a workaround please
+ let us know so we can implement it.
+
+
+Certain patterns of ISA DMA access used for most PC sound cards cause the
+VIA chipsets to lock up. From the collected reports this appears to cover a
+wide range of boards. Some also lock up with sound cards under Win* as well.
+
+Linux implements a workaround providing your chipset is PCI and you compiled
+with PCI Quirks enabled. If so you will see a message
+ "Activating ISA DMA bug workarounds"
+
+during booting. If you have a VIA PCI chipset that hangs when you use the
+sound and is not generating this message even with PCI quirks enabled
+please report the information to the linux-kernel list (see REPORTING-BUGS).
+
+If you are one of the tiny number of unfortunates with a 486 ISA/VLB VIA
+chipset board you need to do the following to build a special kernel for
+your board
+
+ edit linux/include/asm-i386/dma.h
+
+change
+
+#define isa_dma_bridge_buggy (0)
+
+to
+
+#define isa_dma_bridge_buggy (1)
+
+and rebuild a kernel without PCI quirk support.
+
+
+Other than this paticular glitch the VIA [M]VP* chipsets appear to work
+perfectly with Linux.
be actually used, not just for the fun of programming it :-)
If you prefer HTML, feel free to visit the Linux-MM homepage
-<http://www.phys.uu.nl/~riel/mm-patch/>...
+<http://humbolt.geo.uu.nl/Linux-MM/>...
==============================================================
To use the mmap interface a user first sets the desired image size and depth
properties. Next the VIDIOCGMBUF ioctl is issued. This reports the size
of buffer to mmap and the offset within the buffer for each frame. The
-number of frames supported is device dependant and may only be one.
+number of frames supported is device dependent and may only be one.
<P>
The video_mbuf structure contains the following fields
<P>
VERSION = 2
PATCHLEVEL = 2
SUBLEVEL = 0
-EXTRAVERSION =-pre5
+EXTRAVERSION =-pre6
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
- If you install the full sources, do a
cd /usr/src
- gzip -cd linux-2.1.XX.tar.gz | tar xfv -
+ gzip -cd linux-2.2.XX.tar.gz | tar xfv -
to get it all put in place. Replace "XX" with the version number of the
latest kernel.
- - You can also upgrade between 2.1.xx releases by patching. Patches are
+ - You can also upgrade between 2.2.xx releases by patching. Patches are
distributed in the traditional gzip and the new bzip2 format. To
install by patching, get all the newer patch files and do
SOFTWARE REQUIREMENTS
- Compiling and running the 2.1.x kernels requires up-to-date
+ Compiling and running the 2.2.x kernels requires up-to-date
versions of various software packages. Consult
./Documentation/Changes for the minimum version numbers required
and how to get updates for these packages. Beware that using
COMPILING the kernel:
- - Make sure you have gcc-2.7.0 or newer available. It seems older gcc
+ - Make sure you have gcc-2.7.2 or newer available. It seems older gcc
versions can have problems compiling newer versions of Linux. This
is mainly because the older compilers can only generate "a.out"-format
executables. As of Linux 2.1.0, the kernel must be compiled as an
--- /dev/null
+[Some of this is taken from Frohwalt Egerer's original linux-kernel FAQ]
+
+ What follows is a suggested proceedure for reporting Linux bugs. You
+aren't obliged to use the bug reporting format, it is provided as a guide
+to the kind of information that can be useful to developers - no more.
+
+ If the failure includes an "OOPS:" type message in your log or on
+screen please read "Documentation/oops-tracing.txt" before posting your
+bug report. This explains what you should do with the "Oops" information
+to make it useful to the recipient.
+
+ Send the output the maintainer of the kernel area that seems to
+be involved with the problem. Don't worry too much about getting the
+wrong person. If you are unsure send it to the person responsible for the
+code relevant to what you were doing. If it occurs repeatably try and
+describe how to recreate it. That is worth even more than the oops itself.
+The list of maintainers is in the MAINTAINERS file in this directory.
+
+ If you are totally stumped as to whom to send the report, send it to
+linux-kernel@vger.rutgers.edu. (For more information on the linux-kernel
+mailing list see http://www.tux.org/lkml/).
+
+This is a suggested format for a bug report sent to the Linux kernel mailing
+list. Having a standardized bug report form makes it easier for you not to
+overlook things, and easier for the developers to find the pieces of
+information they're really interested in.
+
+ First run the ver_linux script included as scripts/ver_linux or
+at <URL:ftp://ftp.sai.msu.su//sai2/ftp/pub/Linux/ver_linux> It checks out
+the version of some important subsystems. Run it with the commnd
+"sh scripts/ver_linux"
+
+Use that information to fill in all fields of the bug report form, and
+post it to the mailing list with a subject of "ISSUE: <one line
+summary from [1.]>" for easy identification by the developers
+
+[1.] One line summary of the problem:
+[2.] Full description of the problem/report:
+[3.] Keywords (i.e., modules, networking, kernel):
+[4.] Kernel version (from /proc/version):
+[5.] Output of Oops.. message (if applicable) with symbolic information
+ resolved (see Documentation/oops-tracing.txt)
+[6.] A small shell script or example program which triggers the
+ problem (if possible)
+[7.] Environment
+[7.1.] Software (add the output of the ver_linux script here)
+[7.2.] Processor information (from /proc/cpuinfo):
+[7.3.] Module information (from /proc/modules):
+[7.4.] SCSI information (from /proc/scsi/scsi)
+[7.5.] Other information that might be relevant to the problem
+ (please look in /proc and include all information that you
+ think to be relevant):
+[X.] Other notes, patches, fixes, workarounds:
+
+
+Thank you
unsigned long init_user_stack[1024] = { STACK_MAGIC, };
static struct vm_area_struct init_mmap = INIT_MMAP;
static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
static struct files_struct init_files = INIT_FILES;
static struct signal_struct init_signals = INIT_SIGNALS;
struct mm_struct init_mm = INIT_MM;
bool ' Power off on shutdown' CONFIG_APM_POWER_OFF
bool ' Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
bool ' Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+ bool ' RTC stores time in GMT' CONFIG_APM_RTC_IS_GMT
+ bool ' Allow interrupts during APM BIOS calls' CONFIG_APM_ALLOW_INTS
fi
endmenu
* Aug 1998, Version 1.5
* Sep 1998, Version 1.6
* Nov 1998, Version 1.7
+ * Jan 1999, Version 1.8
*
* History:
* 0.6b: first version in official kernel, Linux 1.3.46
* Make boot messages far less verbose by default
* Make asm safer
* Stephen Rothwell
+ * 1.8: Add CONFIG_APM_RTC_IS_GMT
+ * Richard Gooch <rgooch@atnf.csiro.au>
+ * change APM_NOINTS to CONFIG_APM_ALLOW_INTS
+ * remove dependency on CONFIG_PROC_FS
+ * Stephen Rothwell
*
* APM 1.1 Reference:
*
#include <linux/fcntl.h>
#include <linux/malloc.h>
#include <linux/linkage.h>
-#ifdef CONFIG_PROC_FS
#include <linux/stat.h>
#include <linux/proc_fs.h>
-#endif
#include <linux/miscdevice.h>
#include <linux/apm_bios.h>
#include <linux/init.h>
*/
#define ALWAYS_CALL_BUSY
-/*
- * Define to disable interrupts in APM BIOS calls (the CPU Idle BIOS call
- * should turn interrupts on before it does a 'hlt').
- * This reportedly needs undefining for the ThinkPad 600.
- */
-#define APM_NOINTS
-
/*
* Define to make the APM BIOS calls zero all data segment registers (so
* that an incorrect BIOS implementation will cause a kernel panic if it
static unsigned int do_poll(struct file *, poll_table *);
static int do_ioctl(struct inode *, struct file *, u_int, u_long);
-#ifdef CONFIG_PROC_FS
static int apm_get_info(char *, char **, off_t, int, int);
-#endif
extern int apm_register_callback(int (*)(apm_event_t));
extern void apm_unregister_callback(int (*)(apm_event_t));
static int waiting_for_resume = 0;
#endif
+#ifdef CONFIG_APM_RTC_IS_GMT
+# define clock_cmos_diff 0
+# define got_clock_diff 1
+#else
static long clock_cmos_diff;
static int got_clock_diff = 0;
+#endif
static int debug = 0;
static int apm_disabled = 0;
static struct timer_list apm_timer;
-static char driver_version[] = "1.7"; /* no spaces */
+static char driver_version[] = "1.8"; /* no spaces */
#ifdef APM_DEBUG
static char * apm_event_name[] = {
#define ERROR_COUNT (sizeof(error_table)/sizeof(lookup_t))
/*
- * These are the actual BIOS calls. Depending on APM_ZERO_SEGS
- * and APM_NOINTS, we are being really paranoid here! Not only are
- * interrupts disabled, but all the segment registers (except SS) are
- * saved and zeroed this means that if the BIOS tries to reference any
- * data without explicitly loading the segment registers, the kernel will
- * fault immediately rather than have some unforeseen circumstances for
- * the rest of the kernel. And it will be very obvious! :-) Doing this
- * depends on CS referring to the same physical memory as DS so that DS
- * can be zeroed before the call. Unfortunately, we can't do anything
+ * These are the actual BIOS calls. Depending on APM_ZERO_SEGS and
+ * CONFIG_APM_ALLOW_INTS, we are being really paranoid here! Not only
+ * are interrupts disabled, but all the segment registers (except SS)
+ * are saved and zeroed this means that if the BIOS tries to reference
+ * any data without explicitly loading the segment registers, the kernel
+ * will fault immediately rather than have some unforeseen circumstances
+ * for the rest of the kernel. And it will be very obvious! :-) Doing
+ * this depends on CS referring to the same physical memory as DS so that
+ * DS can be zeroed before the call. Unfortunately, we can't do anything
* about the stack segment/pointer. Also, we tell the compiler that
* everything could change.
*
* Also, we KNOW that for the non error case of apm_bios_call, there
* is no useful data returned in the low order 8 bits of eax.
*/
-#ifdef APM_NOINTS
+#ifndef CONFIG_APM_ALLOW_INTS
# define APM_DO_CLI __cli()
#else
# define APM_DO_CLI
unsigned long flags;
int err;
- /* Estimate time zone so that set_time can
- update the clock */
+#ifndef CONFIG_APM_RTC_IS_GMT
+ /*
+ * Estimate time zone so that set_time can update the clock
+ */
save_flags(flags);
clock_cmos_diff = -get_cmos_time();
cli();
clock_cmos_diff += CURRENT_TIME;
got_clock_diff = 1;
restore_flags(flags);
+#endif
err = apm_set_power_state(APM_STATE_SUSPEND);
if (err)
apm_event_t event;
#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
static unsigned long last_resume = 0;
- static int did_resume = 0;
+ static int ignore_bounce = 0;
#endif
while ((event = get_event()) != 0) {
else
printk(KERN_DEBUG "apm: received unknown "
"event 0x%02x\n", event);
+#endif
+#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+ if (ignore_bounce && ((jiffies - last_resume) > HZ))
+ ignore_bounce = 0;
#endif
switch (event) {
case APM_SYS_STANDBY:
#endif
case APM_SYS_SUSPEND:
#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
- if (did_resume && ((jiffies - last_resume) < HZ))
+ if (ignore_bounce)
break;
#endif
#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
#endif
#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
last_resume = jiffies;
- did_resume = 1;
+ ignore_bounce = 1;
#endif
set_time();
send_event(event, 0, NULL);
return 0;
}
-#ifdef CONFIG_PROC_FS
int apm_get_info(char *buf, char **start, off_t fpos, int length, int dummy)
{
char * p;
return p - buf;
}
-#endif
void __init apm_setup(char *str, int *dummy)
{
apm_timer.expires = APM_CHECK_TIMEOUT + jiffies;
add_timer(&apm_timer);
-#ifdef CONFIG_PROC_FS
ent = create_proc_entry("apm", 0, 0);
- ent->get_info = apm_get_info;
-#endif
+ if (ent != NULL)
+ ent->get_info = apm_get_info;
misc_register(&apm_device);
.long SYMBOL_NAME(sys_sendfile)
.long SYMBOL_NAME(sys_ni_syscall) /* streams1 */
.long SYMBOL_NAME(sys_ni_syscall) /* streams2 */
+ .long SYMBOL_NAME(sys_vfork) /* 190 */
/*
- * NOTE!! This doesn' thave to be exact - we just have
+ * NOTE!! This doesn't have to be exact - we just have
* to make sure we have _enough_ of the "sys_ni_syscall"
* entries. Don't panic if you notice that this hasn't
* been shrunk every time we add a new system call.
*/
- .rept NR_syscalls-189
+ .rept NR_syscalls-190
.long SYMBOL_NAME(sys_ni_syscall)
.endr
return do_fork(clone_flags, newsp, ®s);
}
+asmlinkage int sys_vfork(struct pt_regs regs)
+{
+ int child;
+
+ child = do_fork(CLONE_VM | SIGCHLD, regs.esp, ®s);
+
+ if (child > 0)
+ sleep_on(¤t->vfork_sleep);
+
+ return child;
+}
+
/*
* sys_execve() executes a new program.
*/
extern int _stext, _etext;
static void print_child_state(struct task_struct *task)
{
- unsigned int * stack = (unsigned int *) task->tss.esp0;
+ unsigned int * stack = (unsigned int *) task->tss.esp;
int count = 40;
printk("Process: %s (stack=%p, task=%p)\n", task->comm, stack, task);
unsigned int data;
if ((unsigned int) stack < (unsigned int) task)
break;
- if ((unsigned int) stack >= PAGE_SIZE + (unsigned int) task)
+ if ((unsigned int) stack >= 2*PAGE_SIZE + (unsigned int) task)
break;
data = *stack;
stack++;
ret = 0;
goto out;
}
- if (pid == 1) /* you may not mess with init */
- goto out;
ret = -ESRCH;
read_lock(&tasklist_lock);
child = find_task_by_pid(pid);
read_unlock(&tasklist_lock); /* FIXME!!! */
if (!child)
goto out;
+print_child_state(child);
ret = -EPERM;
+ if (pid == 1) /* you may not mess with init */
+ goto out;
if (request == PTRACE_ATTACH) {
if (child == current)
goto out;
if (!(child->flags & PF_PTRACED))
goto out;
if (child->state != TASK_STOPPED) {
-print_child_state(child);
-goto out;
if (request != PTRACE_KILL)
goto out;
}
else
printk("%s", c->x86_model_id);
- if (c->x86_mask)
+ if (c->x86_mask || c->cpuid_level>=0)
printk(" stepping %02x", c->x86_mask);
if(c->x86_vendor == X86_VENDOR_CENTAUR)
* - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
* they're executed irq level is set to the previous
* one, but handlers don't need to be reentrant, if
- * reentrance occured, slow handlers will be just
+ * reentrance occurred, slow handlers will be just
* called again.
* The whole interrupt handling for CIAs is moved to cia.c
* /Roman Zippel
for (;;) {
for (; node; node = node->next)
node->handler(irq, node->dev_id, fp);
- /* if reentrance occured, serve slow handlers again */
+ /* if reentrance occurred, serve slow handlers again */
custom.intena = ami_intena_vals[irq];
if (!server->reentrance) {
server->count--;
dn_irqs[irq-160].handler(irq,dn_irqs[irq-160].dev_id,fp);
}
else {
- printk("spurious irq %d occured\n",irq);
+ printk("spurious irq %d occurred\n",irq);
}
#if 0
: "a0");
#undef frame_offset
/*
- * If we ever get here an exception occured while
+ * If we ever get here an exception occurred while
* building the above stack-frame.
*/
goto badframe;
: "a0");
#undef frame_offset
/*
- * If we ever get here an exception occured while
+ * If we ever get here an exception occurred while
* building the above stack-frame.
*/
goto badframe;
* - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
* they're executed irq level is set to the previous
* one, but handlers don't need to be reentrant, if
- * reentrance occured, slow handlers will be just
+ * reentrance occurred, slow handlers will be just
* called again.
* The whole interrupt handling for CIAs is moved to cia.c
* /Roman Zippel
for (;;) {
for (; node; node = node->next)
node->handler(irq, node->dev_id, fp);
- /* if reentrance occured, serve slow handlers again */
+ /* if reentrance occurred, serve slow handlers again */
custom.intena = ami_intena_vals[irq];
if (!server->reentrance) {
server->count--;
--- /dev/null
+/*
+ * COM1 NS16550 support
+ */
+
+#include "ns16550.h"
+typedef struct NS16550 *NS16550_t;
+
+const NS16550_t COM_PORTS[] = { (NS16550_t) COM1,
+ (NS16550_t) COM2,
+ (NS16550_t) COM3,
+ (NS16550_t) COM4 };
+
+volatile struct NS16550 *
+NS16550_init(int chan)
+{
+ volatile struct NS16550 *com_port;
+ volatile unsigned char xx;
+ com_port = (struct NS16550 *) COM_PORTS[chan];
+ /* See if port is present */
+ com_port->lcr = 0x00;
+ com_port->ier = 0xFF;
+#if 0
+ if (com_port->ier != 0x0F) return ((struct NS16550 *)0);
+#endif
+ com_port->ier = 0x00;
+ com_port->lcr = 0x80; /* Access baud rate */
+ com_port->dll = 0xc; /* 9600 baud */
+ com_port->dlm = 0xc >> 8;
+ com_port->lcr = 0x03; /* 8 data, 1 stop, no parity */
+ com_port->mcr = 0x03; /* RTS/DTR */
+ com_port->fcr = 0x07; /* Clear & enable FIFOs */
+ return (com_port);
+}
+
+
+NS16550_putc(volatile struct NS16550 *com_port, unsigned char c)
+{
+ volatile int i;
+ while ((com_port->lsr & LSR_THRE) == 0) ;
+ com_port->thr = c;
+}
+
+unsigned char
+NS16550_getc(volatile struct NS16550 *com_port)
+{
+ while ((com_port->lsr & LSR_DR) == 0) ;
+ return (com_port->rbr);
+}
+
+NS16550_tstc(volatile struct NS16550 *com_port)
+{
+ return ((com_port->lsr & LSR_DR) != 0);
+}
+
+
+
--- /dev/null
+/*
+ * NS16550 Serial Port
+ */
+
+struct NS16550
+ {
+ unsigned char rbr; /* 0 */
+ unsigned char ier; /* 1 */
+ unsigned char fcr; /* 2 */
+ unsigned char lcr; /* 3 */
+ unsigned char mcr; /* 4 */
+ unsigned char lsr; /* 5 */
+ unsigned char msr; /* 6 */
+ unsigned char scr; /* 7 */
+ };
+
+#define thr rbr
+#define iir fcr
+#define dll rbr
+#define dlm ier
+
+#define LSR_DR 0x01 /* Data ready */
+#define LSR_OE 0x02 /* Overrun */
+#define LSR_PE 0x04 /* Parity error */
+#define LSR_FE 0x08 /* Framing error */
+#define LSR_BI 0x10 /* Break */
+#define LSR_THRE 0x20 /* Xmit holding register empty */
+#define LSR_TEMT 0x40 /* Xmitter empty */
+#define LSR_ERR 0x80 /* Error */
+
+#define COM1 0x800003F8
+#define COM2 0x800002F8
+#define COM3 0x800003F8
+#define COM4 0x80000388
CONFIG_FB_CONTROL=y
CONFIG_FB_PLATINUM=y
CONFIG_FB_VALKYRIE=y
-# CONFIG_FB_ATY is not set
+CONFIG_FB_ATY=y
CONFIG_FB_IMSTT=y
CONFIG_FB_CT65550=y
# CONFIG_FB_S3TRIO is not set
# CONFIG_FB_MATROX is not set
-# CONFIG_FB_ATY is not set
+CONFIG_FB_ATY=y
# CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set
CONFIG_FBCON_CFB8=y
CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
CONFIG_FBCON_CFB32=y
# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
CONFIG_FBCON_FONTS=y
/*
- * $Id: mbx_setup.c,v 1.4 1998/11/15 19:58:55 cort Exp $
+ * $Id: mbx_setup.c,v 1.5 1998/12/29 18:55:07 cort Exp $
*
* linux/arch/ppc/kernel/setup.c
*
void __init powermac_init(void)
{
}
+
void __init adbdev_init(void)
{
}
void __init mbx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
{
-
- *p = 0;
- *irq = 0;
-
- if (base != 0) /* Only map the first ATA flash drive */
- return;
+ ide_ioreg_t port = base;
+ int i = 8;
+
+ while (i--)
+ *p++ = port++;
+ *p++ = base + 0x206;
+ if (irq != NULL)
+ *irq = 0;
#ifdef ATA_FLASH
base = (unsigned long) ioremap(PCMCIA_MEM_ADDR, 0x200);
for (i = 0; i < 8; ++i)
/*
- * $Id: pci.c,v 1.42 1998/12/04 14:31:37 cort Exp $
+ * $Id: pci.c,v 1.43 1998/12/29 18:55:11 cort Exp $
* Common pmac/prep/chrp pci routines. -- Cort
*/
__initfunc(void
setup_pci_ptrs(void))
{
- PPC_DEVICE *hostbridge;
#ifndef CONFIG_MBX
+ PPC_DEVICE *hostbridge;
switch (_machine) {
case _MACH_prep:
hostbridge=residual_find_device(PROCESSORDEVICE, NULL,
extern struct bridge_data **bridges;
extern unsigned char *Motherboard_map;
extern unsigned char *Motherboard_routes;
+ unsigned char i;
#ifndef CONFIG_MBX
switch (_machine )
{
* irq this device uses. This is necessary on things
* without residual data. -- Cort
*/
- unsigned char d = PCI_SLOT(dev->devfn), i;
+ unsigned char d = PCI_SLOT(dev->devfn);
dev->irq = Motherboard_routes[Motherboard_map[d]];
for ( i = 0 ; i <= 5 ; i++ )
{
EXPORT_SYMBOL(find_path_device);
EXPORT_SYMBOL(find_phandle);
EXPORT_SYMBOL(get_property);
+EXPORT_SYMBOL(device_is_compatible);
EXPORT_SYMBOL(pci_io_base);
EXPORT_SYMBOL(pci_device_loc);
EXPORT_SYMBOL(feature_set);
/*
- * $Id: process.c,v 1.69 1998/12/28 10:28:49 paulus Exp $
+ * $Id: process.c,v 1.70 1999/01/07 16:28:59 cort Exp $
*
* linux/arch/ppc/kernel/process.c
*
_enable_interrupts(s);
}
-void instruction_dump (unsigned long *pc)
-{
- int i;
-
- if((((unsigned long) pc) & 3))
- return;
-
- printk("Instruction DUMP:");
- for(i = -3; i < 6; i++)
- printk("%c%08lx%c",i?' ':'<',pc[i],i?' ':'>');
- printk("\n");
-}
-
void show_regs(struct pt_regs * regs)
{
int i;
out:
}
+void instruction_dump (unsigned long *pc)
+{
+ int i;
+
+ if((((unsigned long) pc) & 3))
+ return;
+
+ printk("Instruction DUMP:");
+ for(i = -3; i < 6; i++)
+ printk("%c%08lx%c",i?' ':'<',pc[i],i?' ':'>');
+ printk("\n");
+}
+
void exit_thread(void)
{
if (last_task_used_math == current)
/*
- * $Id: setup.c,v 1.120 1998/12/10 00:24:28 cort Exp $
+ * $Id: setup.c,v 1.122 1998/12/31 20:51:19 cort Exp $
* Common prep/pmac/chrp boot and setup code.
*/
break;
}
#endif
+#if defined(CONFIG_MBX)
+ mbx_ide_init_hwif_ports(p,base,irq);
+#endif
}
EXPORT_SYMBOL(ide_init_hwif_ports);
#endif
* Find out what kind of machine we're on and save any data we need
* from the early boot process (devtree is copied on pmac by prom_init() )
*/
-__initfunc(unsigned long
+unsigned long __init
identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7))
+ unsigned long r6, unsigned long r7)
{
extern void setup_pci_ptrs(void);
char *model;
have_of = 1;
+
+ /* prom_init has already been called from __start */
+ finish_device_tree();
/* ask the OF info if we're a chrp or pmac */
model = get_property(find_path_device("/"), "device_type", NULL);
if ( model && !strncmp("chrp",model,4) )
if ( have_of )
{
+#ifdef CONFIG_MACH_SPECIFIC
/* prom_init has already been called from __start */
finish_device_tree();
+#endif /* CONFIG_MACH_SPECIFIC */
/*
* If we were booted via quik, r3 points to the physical
* address of the command-line parameters.
/*
- * $Id: init.c,v 1.138 1998/12/15 17:34:43 cort Exp $
+ * $Id: init.c,v 1.139 1998/12/29 19:53:49 cort Exp $
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
ioremap(MBX_CSR_ADDR, MBX_CSR_SIZE);
ioremap(IMAP_ADDR, IMAP_SIZE);
ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
+ /* ide needs to be able to get at PCI space -- Cort */
+ ioremap(0x80000000, 0x4000);
#endif /* CONFIG_8xx */
}
/*
* This finds the amount of physical ram and does necessary
* setup for prep. This is pretty architecture specific so
- * this will likely stay seperate from the pmac.
+ * this will likely stay separate from the pmac.
* -- Cort
*/
__initfunc(unsigned long *prep_find_end_of_memory(void))
/* %o1 is dst
* %o3 is # bytes to zero out
* %o4 is faulting address
- * %o5 is %pc where fault occured */
+ * %o5 is %pc where fault occurred */
clr %o2
31:
/* %o0 is src
* %o2 is # of bytes to copy from src to dst
* %o3 is # bytes to zero out
* %o4 is faulting address
- * %o5 is %pc where fault occured */
+ * %o5 is %pc where fault occurred */
save %sp, -104, %sp
mov %i5, %o0
mov %i7, %o1
static void fd_times_out(unsigned long dummy)
{
SET_IRQ_HANDLER(NULL);
- /* If the timeout occured while the readtrack_check timer was
+ /* If the timeout occurred while the readtrack_check timer was
* active, we need to cancel it, else bad things will happen */
del_timer( &readtrack_timer );
FDC1772_WRITE(FDC1772REG_CMD, FDC1772CMD_FORCI);
* bad_dma_drives() lists the model names (from "hdparm -i")
* of drives which supposedly support (U)DMA but which are
* known to corrupt data with this interface under Linux.
+ *
+ * This is an empirical list. Its generated from bug reports. That means
+ * while it reflects actual problem distributions it doesn't answer whether
+ * the drive or the controller, or cabling, or software, or some combination
+ * thereof is the fault. If you don't happen to agree with the kernel's
+ * opinion of your drive - use hdparm to turn DMA on.
*/
const char *bad_dma_drives[] = {"WDC AC11000H",
"WDC AC22100H",
"WDC AC32500H",
"WDC AC33100H",
+ "WDC AC31600H",
NULL};
/*
list = bad_dma_drives;
while (*list) {
if (!strcmp(*list++,id->model)) {
- printk("%s: (U)DMA capability is broken for %s\n",
+ printk("%s: Disabling (U)DMA for %s\n",
drive->name, id->model);
return 1;
}
/*
* Some tape drives require a long irq timeout
*/
-#define IDETAPE_WAIT_CMD 60
+#define IDETAPE_WAIT_CMD (60*HZ)
/*
* DSC timings.
xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
((u_short *) (buf))[0xD8],((u_short *) (buf))[0xDA],buf[0x1B4]);
}
- /* 1002 based RLL controler requests converted adressing, but reports physical
+ /* 1002 based RLL controler requests converted addressing, but reports physical
(physical 26 sec., logical 17 sec.)
1004 based ???? */
if (rll & wd_1002) {
cdo->lock_door(cdi, 1);
cdinfo(CD_OPEN, "door locked.\n");
}
- cdinfo(CD_OPEN, "device opened sucessfully.\n");
+ cdinfo(CD_OPEN, "device opened successfully.\n");
return ret;
/* Something failed. Try to unlock the drive, because some drivers
sanitize_format(&ms_info.addr, &ms_info.addr_format,
requested_format);
IOCTL_OUT(arg, struct cdrom_multisession, ms_info);
- cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION sucessful\n");
+ cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n");
return 0;
}
if ((ret=cdo->get_mcn(cdi, &mcn)))
return ret;
IOCTL_OUT(arg, struct cdrom_mcn, mcn);
- cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN sucessful\n");
+ cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN successful\n");
return 0;
}
sanitize_format(&q.cdsc_absaddr, &back, requested);
sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
IOCTL_OUT(arg, struct cdrom_subchnl, q);
- /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL sucessful\n"); */
+ /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */
return 0;
}
case CDROMREADTOCHDR: {
if ((ret=cdo->audio_ioctl(cdi, cmd, &header)))
return ret;
IOCTL_OUT(arg, struct cdrom_tochdr, header);
- /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR sucessful\n"); */
+ /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */
return 0;
}
case CDROMREADTOCENTRY: {
sanitize_format(&entry.cdte_addr,
&entry.cdte_format, requested_format);
IOCTL_OUT(arg, struct cdrom_tocentry, entry);
- /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY sucessful\n"); */
+ /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */
return 0;
}
case CDROMPLAYMSF: {
# define CDU535_MESSAGE_NAME "Sony CDU-535"
#endif
+#define CDU535_BLOCK_SIZE 2048
+
#ifndef MAX_SPINUP_RETRY
# define MAX_SPINUP_RETRY 3 /* 1 is sufficient for most drives... */
#endif
seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
Byte **buff, int buf_size)
{
- const int block_size = 2048;
Byte cmd_buff[7];
int i;
int read_status;
Byte *data_buff;
int sector_count = 0;
- if (buf_size < ((long)block_size) * n_blocks)
+ if (buf_size < CDU535_BLOCK_SIZE * n_blocks)
return NO_ROOM;
set_drive_mode(SONY535_CDROM_DRIVE_MODE, status);
if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) {
/* data is ready, read it */
data_buff = buff[sector_count++];
- for (i = 0; i < block_size; i++)
+ for (i = 0; i < CDU535_BLOCK_SIZE; i++)
*data_buff++ = inb(data_reg); /* unrolling this loop does not seem to help */
data_valid = 1;
break; /* exit the timeout loop */
/* read all the data, now read the status */
if ((i = read_exec_status(status)) != 0)
return i;
- return block_size * sector_count;
+ return CDU535_BLOCK_SIZE * sector_count;
} /* seek_and_read_N_blocks() */
/****************************************************************************
* The OS calls this to perform a read or write operation to the drive.
* Write obviously fail. Reads to a read ahead of sony_buffer_size
* bytes to help speed operations. This especially helps since the OS
- * uses 1024 byte blocks and the drive uses 2048 byte blocks. Since most
+ * may use 1024 byte blocks and the drive uses 2048 byte blocks. Since most
* data access on a CD is done sequentially, this saves a lot of operations.
*/
static void
* seek_and_read_N_blocks for the various cases.
*/
int readStatus = seek_and_read_N_blocks(params, read_size,
- status, sony_buffer, (read_size * 2048));
+ status, sony_buffer, (read_size * CDU535_BLOCK_SIZE));
if (0 <= readStatus) /* Good data; common case, placed first */
break;
if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
NULL /* revalidate */
};
+static int sonycd535_block_size = CDU535_BLOCK_SIZE;
+
/*
* Initialize the driver.
*/
if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) == 0) {
/* set the drive mode successful, we are set! */
sony_buffer_size = SONY535_BUFFER_SIZE;
- sony_buffer_sectors = sony_buffer_size / 2048;
+ sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE;
printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
drive_config.vendor_id,
return -EIO;
}
blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+ blksize_size[MAJOR_NR] = &sonycd535_block_size;
read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read-ahead */
sony_toc = (struct s535_sony_toc *)
return -ENOMEM;
}
for (i = 0; i < sony_buffer_sectors; i++) {
- sony_buffer[i] = (Byte *)kmalloc(2048, GFP_KERNEL);
+ sony_buffer[i] =
+ (Byte *)kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL);
if (sony_buffer[i] == NULL) {
while (--i>=0)
kfree(sony_buffer[i]);
release_region(sony535_cd_base_io, 4);
for (i = 0; i < sony_buffer_sectors; i++)
- kfree_s(sony_buffer[i], 2048);
+ kfree_s(sony_buffer[i], CDU535_BLOCK_SIZE);
kfree_s(sony_buffer, 4 * sony_buffer_sectors);
kfree_s(last_sony_subcode, sizeof *last_sony_subcode);
kfree_s(sony_toc, sizeof *sony_toc);
current digiConfig application does not provide this function for PCI cards
(Though it does build device nodes for non-PCI cards). To use this program
execute the following:first install the driver, and execute digiDload (See above). After digiDload
- has sucessfully loaded, execute the following:
+ has successfully loaded, execute the following:
buildPCI <arg1> <arg2>
Linux kernels support higher baud rates by using
0x1000 bit. When the returned value (ored with
0x1000) was used to reference our fbaud table a
- serious memory problem occured. This has been fixed.
+ serious memory problem occurred. This has been fixed.
4. Added a request_region call to post_fep_init. This
should cause the i/o ports being used to be
found in epcaconfig.h; if so it DOESN'T load
epcaconfig data depending on epca_setup to handle
board configuration. pc_open has been modified
- such that it checks to insure that no errors
- occured during the LILO boot process. If a
+ such that it checks to ensure that no errors
+ occurred during the LILO boot process. If a
user attempts to boot the driver (via. LILO)
with incorrect data, the open will fail.
return 0;
}
+static void con_close(struct tty_struct *tty, struct file * filp)
+{
+ if (tty->count == 1)
+ tty->driver_data = 0;
+}
+
static void vc_init(unsigned int currcons, unsigned int rows, unsigned int cols, int do_clear)
{
int j, k ;
console_driver.termios_locked = console_termios_locked;
console_driver.open = con_open;
+ console_driver.close = con_close;
console_driver.write = con_write;
console_driver.write_room = con_write_room;
console_driver.put_char = con_put_char;
tty = ttytab? ttytab[fg_console]: NULL;
if (tty && (!tty->driver_data)) {
- /* This is to workaround ugly bug in tty_io.c, which
- does not do locking when it should */
+ /*
+ * We touch the tty structure via the the ttytab array
+ * without knowing whether or not tty is open, which
+ * is inherently dangerous. We currently rely on that
+ * fact that console_open sets tty->driver_data when
+ * it opens it, and clears it when it closes it.
+ */
tty = NULL;
}
kbd = kbd_table + fg_console;
*/
static void check_unthrottle(struct tty_struct * tty)
{
- if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
+ if (tty->count &&
+ test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
tty->driver.unthrottle)
tty->driver.unthrottle(tty);
}
add_wait_queue(&tty->read_wait, &wait);
- disable_bh(TQUEUE_BH);
+ if (down_interruptible(&tty->atomic_read))
+ return -ERESTARTSYS;
+ set_bit(TTY_DONT_FLIP, &tty->flags);
while (nr) {
/* First test for status change. */
if (tty->packet && tty->link->ctrl_status) {
+ unsigned char cs;
if (b != buf)
break;
- put_user(tty->link->ctrl_status, b++);
- nr--;
+ cs = tty->link->ctrl_status;
tty->link->ctrl_status = 0;
+ put_user(cs, b++);
+ nr--;
break;
}
/* This statement must be first before checking for input
retval = -ERESTARTSYS;
break;
}
- enable_bh(TQUEUE_BH);
+ clear_bit(TTY_DONT_FLIP, &tty->flags);
timeout = schedule_timeout(timeout);
- disable_bh(TQUEUE_BH);
+ set_bit(TTY_DONT_FLIP, &tty->flags);
continue;
}
current->state = TASK_RUNNING;
if (time)
timeout = time;
}
- enable_bh(TQUEUE_BH);
+ clear_bit(TTY_DONT_FLIP, &tty->flags);
+ up(&tty->atomic_read);
remove_wait_queue(&tty->read_wait, &wait);
if (!waitqueue_active(&tty->read_wait))
* to get fine volume control over the low volume range.
*
* Some code derived from code by Frans Brinkman
+ *
+ * 1999-01-05 - (C. van Schaik)
+ * - Changed tuning to 1/160Mhz accuracy
+ * - Added stereo support
+ * (card defaults to stereo)
+ * (can explicitly force mono on the card)
+ * (can detect if station is in stereo)
+ * - Added unmute function
+ * - Reworked ioctl functions
*/
#include <linux/module.h> /* Modules */
int curvol;
unsigned long curfreq;
int muted;
+ unsigned int stereo;
};
}
}
+static int zol_setvol(struct zol_device *dev, int vol)
+{
+ dev->curvol = vol;
+ if (dev->muted)
+ return 0;
+
+ if (vol == 0) {
+ outb(0, io);
+ outb(0, io);
+ inb(io + 3); /* Zoltrix needs to be read to confirm */
+ return 0;
+ }
+
+ outb(dev->curvol-1, io);
+ sleep_delay(10000);
+ inb(io + 2);
+
+ return 0;
+}
+
static void zol_mute(struct zol_device *dev)
{
dev->muted = 1;
outb(0, io);
outb(0, io);
- inb(io + 3); /* Zoltrix needs to be read to confirm */
-}
-
-static void zol_on(int vol)
-{
- int l;
- outb(vol, io);
- sleep_delay(10000);
- l = inb(io + 2);
+ inb(io + 3); /* Zoltrix needs to be read to confirm */
}
-static int zol_setvol(struct zol_device *dev, int vol)
+static void zol_unmute(struct zol_device *dev)
{
- if (vol == dev->curvol) { /* requested volume = current */
- if (dev->muted) { /* user is unmuting the card */
- dev->muted = 0;
- zol_on(vol);
- }
- return 0;
- }
- if (vol == 0) { /* volume = 0 means mute the card */
- zol_mute(dev);
- return 0;
- }
dev->muted = 0;
- dev->curvol = vol;
-
- zol_on(vol);
-
- return 0;
+ zol_setvol(dev, dev->curvol);
}
static int zol_setfreq(struct zol_device *dev, unsigned long freq)
{
/* tunes the radio to the desired frequency */
unsigned long long bitmask, f, m;
+ unsigned int stereo = dev->stereo;
int i;
- m = (freq * 25 / 4 - 8800) * 2;
+ if (freq == 0)
+ return 1;
+ m = (freq / 160 - 8800) * 2;
f = (unsigned long long) m + 0x4d1c;
bitmask = 0xc480402c10080000ull;
i = 45;
- zol_mute(dev);
+ outb(0, io);
+ outb(0, io);
+ inb(io + 3); /* Zoltrix needs to be read to confirm */
outb(0x40, io);
outb(0xc0, io);
- bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ ( /*stereo */ 0 << 31));
+ bitmask = (bitmask ^ ((f & 0xff) << 47) ^ ((f & 0xff00) << 30) ^ ( stereo << 31));
while (i--) {
if ((bitmask & 0x8000000000000000ull) != 0) {
outb(0x80, io);
outb(0x80, io);
outb(0xc0, io);
outb(0x40, io);
- zol_on(dev->curvol);
+ sleep_delay(1000);
+ inb(io+2);
+
+ sleep_delay(1000);
+ if (dev->muted)
+ {
+ outb(0, io);
+ outb(0, io);
+ inb(io + 3);
+ sleep_delay(1000);
+ } else
+ zol_setvol(dev, dev->curvol);
return 0;
}
sleep_delay(1000);
b = inb(io);
- if ((a == b) && (a == 0xdf)) /* I found this out by playing */
- /* with a binary scanner on the card io */
- return (1);
- else
+ if (a != b)
return (0);
- if (inb(io) & 2) /* bit set = no signal present */
- return 0;
- return 1; /* signal present */
+ if ((a == 0xcf) || (a == 0xdf) /* I found this out by playing */
+ || (a == 0xef)) /* with a binary scanner on the card io */
+ return (1);
+ return (0);
+}
+
+int zol_is_stereo (struct zol_device *dev)
+{
+ int x1, x2;
+
+ outb(0x00, io);
+ outb(dev->curvol, io);
+ sleep_delay(20000);
+
+ x1 = inb(io);
+ sleep_delay(1000);
+ x2 = inb(io);
+
+ if ((x1 == x2) && (x1 == 0xcf))
+ return 1;
+ return 0;
}
static int zol_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
{
- struct zol_device *rt = dev->priv;
+ struct zol_device *zol = dev->priv;
switch (cmd) {
case VIDIOCGCAP:
{
struct video_capability v;
v.type = VID_TYPE_TUNER;
- v.channels = 1;
+ v.channels = 1 + zol->stereo;
v.audios = 1;
/* No we don't do pictures */
v.maxwidth = 0;
case VIDIOCGTUNER:
{
struct video_tuner v;
- if (copy_from_user(&v, arg, sizeof(v)) != 0)
+/*
+ if (copy_from_user(&v, arg, sizeof(v)))
return -EFAULT;
- if (v.tuner) /* Only 1 tuner */
+ if (v.tuner)
return -EINVAL;
- v.rangelow = (int) (88.0 * 16);
- v.rangehigh = (int) (108.0 * 16);
- v.flags = 0;
+*/
+ v.tuner = 0;
+ strcpy(v.name, "Zoltrix Radio");
+ v.rangelow = (int) (88.0 * 16000);
+ v.rangehigh = (int) (108.0 * 16000);
+ v.flags = zol_is_stereo(zol)
+ ? VIDEO_TUNER_STEREO_ON : 0;
+ v.flags |= VIDEO_TUNER_LOW;
v.mode = VIDEO_MODE_AUTO;
- v.signal = 0xFFFF * zol_getsigstr(rt);
+ v.signal = 0xFFFF * zol_getsigstr(zol);
if (copy_to_user(arg, &v, sizeof(v)))
return -EFAULT;
return 0;
return 0;
}
case VIDIOCGFREQ:
- if (copy_to_user(arg, &rt->curfreq, sizeof(rt->curfreq)))
+ if (copy_to_user(arg, &zol->curfreq, sizeof(zol->curfreq)))
return -EFAULT;
return 0;
case VIDIOCSFREQ:
- if (copy_from_user(&rt->curfreq, arg, sizeof(rt->curfreq)))
+ if (copy_from_user(&zol->curfreq, arg, sizeof(zol->curfreq)))
return -EFAULT;
- zol_setfreq(rt, rt->curfreq);
+ zol_setfreq(zol, zol->curfreq);
return 0;
case VIDIOCGAUDIO:
{
struct video_audio v;
memset(&v, 0, sizeof(v));
v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME;
- v.volume = rt->curvol * 4096;
+ v.mode != zol_is_stereo(zol)
+ ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO;
+ v.volume = zol->curvol * 4096;
v.step = 4096;
- strcpy(v.name, "Radio");
+ strcpy(v.name, "Zoltrix Radio");
if (copy_to_user(arg, &v, sizeof(v)))
return -EFAULT;
return 0;
return -EINVAL;
if (v.flags & VIDEO_AUDIO_MUTE)
- zol_mute(rt);
+ zol_mute(zol);
else
- zol_setvol(rt, v.volume / 4096);
+ zol_unmute(zol);
+
+ if (v.flags & VIDEO_AUDIO_VOLUME)
+ zol_setvol(zol, v.volume / 4096);
+
+ if (v.mode & VIDEO_SOUND_STEREO)
+ {
+ zol->stereo = 1;
+ zol_setfreq(zol, zol->curfreq);
+ }
+ if (v.mode & VIDEO_SOUND_MONO)
+ {
+ zol->stereo = 0;
+ zol_setfreq(zol, zol->curfreq);
+ }
return 0;
}
printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io);
return -EBUSY;
}
+ if ((io != 0x20c) && (io != 0x30c)) {
+ printk(KERN_ERR "zoltrix: invalid port, try 0x20c or 0x30c\n");
+ return -ENXIO;
+ }
zoltrix_radio.priv = &zoltrix_unit;
if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO) == -1)
inb(io + 3);
zoltrix_unit.curvol = 0;
+ zoltrix_unit.stereo = 1;
return 0;
}
* Failures after this point use release_mem to clean up, so
* there's no need to null out the local pointers.
*/
- driver->table[idx] = tty; /* FIXME: this is broken and
- probably causes ^D bug. tty->private_date does not (yet) point
- to a console, if keypress comes now, await armagedon.
-
- also, driver->table is accessed from interrupt for vt case,
- and this does not look like atomic access at all. */
+ driver->table[idx] = tty;
if (!*tp_loc)
*tp_loc = tp;
int count;
unsigned long flags;
+ if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
+ queue_task(&tty->flip.tqueue, &tq_timer);
+ return;
+ }
if (tty->flip.buf_num) {
cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
/*
* Routine which returns the baud rate of the tty
- */
-
-/*
- * This is used to figure out the divisor speeds and the timeouts
+ *
+ * Note that the baud_table needs to be kept in sync with the
+ * include/asm/termbits.h file.
*/
static int baud_table[] = {
0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
- 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
+ 9600, 19200, 38400, 57600, 115200, 230400, 460800,
+#ifdef __sparc__
+ 76800, 153600, 307200, 614400, 921600
+#else
+ 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
+ 2500000, 3000000, 3500000, 4000000
+#endif
+};
+
+static int n_baud_table = sizeof(baud_table)/sizeof(int);
int tty_get_baud_rate(struct tty_struct *tty)
{
i = cflag & CBAUD;
if (i & CBAUDEX) {
i &= ~CBAUDEX;
- if (i < 1 || i > 4)
+ if (i < 1 || i+15 >= n_baud_table)
tty->termios->c_cflag &= ~CBAUDEX;
else
i += 15;
tty->flip.pty_sem = MUTEX;
tty->tq_hangup.routine = do_tty_hangup;
tty->tq_hangup.data = tty;
+ sema_init(&tty->atomic_read, 1);
}
/*
#ifdef MODULE
MODULE_AUTHOR("Fritz Elfert");
MODULE_PARM(portbase, "i");
-MODULE_PARM_DESC(portbase, "Port adress of first card");
+MODULE_PARM_DESC(portbase, "Port address of first card");
MODULE_PARM(membase, "i");
-MODULE_PARM_DESC(membase, "Shared memory adress of all cards");
+MODULE_PARM_DESC(membase, "Shared memory address of all cards");
MODULE_PARM(icn_id, "s");
MODULE_PARM_DESC(icn_id, "ID-String of first card");
MODULE_PARM(icn_id2, "s");
&isdn_x25iface_disconn_ind
};
-/* error message helper fuction */
+/* error message helper function */
static void illegal_state_warn( unsigned state, unsigned char firstbyte)
{
printk( KERN_WARNING "isdn_x25iface: firstbyte %x illegal in"
MIX_OBJS :=
ifeq ($(CONFIG_PARPORT),y)
- L_OBJS += parport_share.o parport_ieee1284.o
- ifeq ($(CONFIG_PROC_FS),y)
- L_OBJS += parport_procfs.o
- endif
+ L_OBJS += parport_share.o parport_ieee1284.o parport_procfs.o
ifeq ($(CONFIG_PARPORT_PC),y)
LX_OBJS += parport_pc.o
else
* a subset of the standard printer control lines connected.
*/
-#include <linux/config.h>
#include <linux/tasks.h>
#include <linux/delay.h>
#include <linux/errno.h>
* Grant Guenther <grant@torque.net>
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/errno.h>
* Cleaned up include files - Russell King <linux@arm.uk.linux.org>
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/errno.h>
vp->tx_skbuff[i] = 0;
outl(0, ioaddr + DownListPtr);
}
- /* Set reciever mode: presumably accept b-case and phys addr only. */
+ /* Set receiver mode: presumably accept b-case and phys addr only. */
set_rx_mode(dev);
outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
/* The 3c523 has a 24K chunk of memory. The first 16K is the
shared memory, while the last 8K is for the EtherStart BIOS ROM.
Which we don't care much about here. We'll just tell Linux that
- we're using 16K. MCA won't permit adress space conflicts caused
+ we're using 16K. MCA won't permit address space conflicts caused
by not mapping the other 8K. */
dev->mem_start = shm_table[(status & ELMC_STATUS_MEMORY_SELECT) >> 3];
*/
static char *version =
-"3c59x.c:v0.99E 5/12/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
+"3c59x.c:v0.99H 11/17/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html\n";
/* "Knobs" that adjust features and parameters. */
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
Setting to > 1512 effectively disables this feature. */
-static const rx_copybreak = 200;
+static const int rx_copybreak = 200;
/* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
-static const mtu = 1500;
+static const int mtu = 1500;
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static int max_interrupt_work = 20;
/* Put out somewhat more debugging messages. (0: no msg, 1 minimal .. 6). */
+#define vortex_debug debug
#ifdef VORTEX_DEBUG
static int vortex_debug = VORTEX_DEBUG;
#else
debugging. */
static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
-/* Enable the automatic media selection code -- usually set. */
-#define AUTOMEDIA 1
-
-/* Allow the use of fragment bus master transfers instead of only
- programmed-I/O for Vortex cards. Full-bus-master transfers are always
- enabled by default on Boomerang cards. If VORTEX_BUS_MASTER is defined,
- the feature may be turned on using 'options'. */
-#define VORTEX_BUS_MASTER
-
/* A few values that may be tweaked. */
/* Time in jiffies before concluding the transmitter is hung. */
#define TX_TIMEOUT ((400*HZ)/1000)
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
#include <linux/config.h>
+#include <linux/version.h>
#ifdef MODULE
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
#include <linux/module.h>
-#include <linux/version.h>
#else
#define MOD_INC_USE_COUNT
#define MOD_DEC_USE_COUNT
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/string.h>
-#include <linux/ptrace.h>
+#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/ioport.h>
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/timer.h>
-
-#include <asm/byteorder.h>
-#include <asm/irq.h> /* For NR_IRQS only. */
-#include <asm/bitops.h>
-#include <asm/io.h>
-
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#if LINUX_VERSION_CODE < 0x20155 || defined(CARDBUS)
+#include <linux/bios32.h>
+#endif
+#include <asm/irq.h> /* For NR_IRQS only. */
+#include <asm/bitops.h>
+#include <asm/io.h>
-/* Kernel compatibility defines, common to David Hind's PCMCIA package.
+/* Kernel compatibility defines, some common to David Hinds' PCMCIA package.
This is only in the support-all-kernels source code. */
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h> /* Redundant above, here for easy clean-up. */
+
+#define RUN_AT(x) (jiffies + (x))
+
+#include <linux/delay.h>
+
+#if (LINUX_VERSION_CODE >= 0x20100)
+char kernel_version[] = UTS_RELEASE;
+#else
+#ifndef __alpha__
+#define ioremap(a,b) \
+ (((a)<0x100000) ? (void *)((u_long)(a)) : vremap(a,b))
+#define iounmap(v) \
+ do { if ((u_long)(v) > 0x100000) vfree(v); } while (0)
#endif
-#if LINUX_VERSION_CODE < 0x10300
-#define RUN_AT(x) (x) /* What to put in timer->expires. */
-#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC)
-#if defined(__alpha)
-#error "The Alpha architecture is only support with kernel version 2.0."
#endif
-#define virt_to_bus(addr) ((unsigned long)addr)
-#define bus_to_virt(addr) ((void*)addr)
-#define NR_IRQS 16
-#else /* 1.3.0 and later */
-#define RUN_AT(x) (jiffies + (x))
-#define DEV_ALLOC_SKB(len) dev_alloc_skb(len)
+#if LINUX_VERSION_CODE <= 0x20139
+#define net_device_stats enet_statistics
+#define NETSTATS_VER2
+#endif
+#if LINUX_VERSION_CODE < 0x20138
+#define test_and_set_bit(val, addr) set_bit(val, addr)
+#define le32_to_cpu(val) (val)
+#define cpu_to_le32(val) (val)
+#endif
+#if LINUX_VERSION_CODE < 0x20155
+#define PCI_SUPPORT_VER1
+#else
+#define PCI_SUPPORT_VER2
#endif
#if LINUX_VERSION_CODE < 0x20159
#define DEV_FREE_SKB(skb) dev_kfree_skb (skb, FREE_WRITE);
#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
#endif
-#ifdef SA_SHIRQ
-#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev)
-#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance)
-#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
-#else
-#define FREE_IRQ(irqnum, dev) free_irq(irqnum)
-#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n)
-#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
-#endif
-
-#if (LINUX_VERSION_CODE >= 0x10344)
-#define NEW_MULTICAST
-#include <linux/delay.h>
-#else
-#define udelay(microsec) do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
-#endif
-
-#if LINUX_VERSION_CODE < 0x20138
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#endif
-#if defined(MODULE) && (LINUX_VERSION_CODE >= 0x20115)
+#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
MODULE_DESCRIPTION("3Com 3c590/3c900 series Vortex/Boomerang driver");
MODULE_PARM(debug, "i");
MODULE_PARM(max_interrupt_work, "i");
MODULE_PARM(compaq_ioaddr, "i");
MODULE_PARM(compaq_irq, "i");
-MODULE_PARM(compaq_prod_id, "i");
+MODULE_PARM(compaq_device_id, "i");
#endif
/* Operational parameter that usually are not changed. */
#define VORTEX_TOTAL_SIZE 0x20
#define BOOMERANG_TOTAL_SIZE 0x40
-#ifdef HAVE_DEVLIST
-struct netdev_entry tc59x_drv =
-{"Vortex", vortex_pci_probe, VORTEX_TOTAL_SIZE, NULL};
-#endif
-
/* Set iff a MII transceiver on any interface requires mdio preamble.
This only set with the original DP83840 on older 3c905 boards, so the extra
code size of a per-interface flag is not worthwhile. */
static char mii_preamble_required = 0;
-/* Caution! These entries must be consistent. */
-static const int product_ids[] = {
- 0x5900, 0x5920, 0x5970, 0x5950, 0x5951, 0x5952, 0x9000, 0x9001,
- 0x9050, 0x9051, 0x9055, 0x5057, 0 };
-static const char *product_names[] = {
- "3c590 Vortex 10Mbps",
- "3c592 EISA 10mbps Demon/Vortex",
- "3c597 EISA Fast Demon/Vortex",
- "3c595 Vortex 100baseTX",
- "3c595 Vortex 100baseT4",
- "3c595 Vortex 100base-MII",
- "3c900 Boomerang 10baseT",
- "3c900 Boomerang 10Mbps/Combo",
- "3c905 Boomerang 100baseTx",
- "3c905 Boomerang 100baseT4",
- "3c905B Cyclone 100baseTx",
- "3c575", /* Cardbus Boomerang */
-};
-
/*
Theory of Operation
versions of the FastEtherLink cards. The supported product IDs are
3c590, 3c592, 3c595, 3c597, 3c900, 3c905
-The ISA 3c515 is supported with a seperate driver, 3c515.c, included with
-the kernel source or available from
+The related ISA 3c515 is supported with a separate driver, 3c515.c, included
+with the kernel source or available from
cesdis.gsfc.nasa.gov:/pub/linux/drivers/3c515.html
II. Board-specific settings
PCI bus devices are configured by the system at boot time, so no jumpers
need to be set on the board. The system BIOS should be set to assign the
-PCI INTA signal to an otherwise unused system IRQ line. While it's
-physically possible to shared PCI interrupt lines, the 1.2.0 kernel doesn't
-support it.
+PCI INTA signal to an otherwise unused system IRQ line.
+
+The EEPROM settings for media type and forced-full-duplex are observed.
+The EEPROM media type should be left at the default "autoselect" unless using
+10base2 or AUI connections which cannot be reliably detected.
III. Driver operation
series. The primary interface is two programmed-I/O FIFOs, with an
alternate single-contiguous-region bus-master transfer (see next).
-The 3c900 "Boomerang" series uses a full-bus-master interface with seperate
+The 3c900 "Boomerang" series uses a full-bus-master interface with separate
lists of transmit and receive descriptors, similar to the AMD LANCE/PCnet,
DEC Tulip and Intel Speedo3. The first chip version retains a compatible
-programmed-I/O interface that will be removed in the 'B' and subsequent
+programmed-I/O interface that has been removed in 'B' and subsequent board
revisions.
One extension that is advertised in a very large font is that the adapters
single frame.
With full-bus-master support, this driver uses a "RX_COPYBREAK" scheme.
-Tather than a fixed intermediate receive buffer, this scheme allocates
+Rather than a fixed intermediate receive buffer, this scheme allocates
full-sized skbuffs as receive buffers. The value RX_COPYBREAK is used as
the copying breakpoint: it is chosen to trade-off the memory wasted by
passing the full-sized skbuff to the queue layer for all frames vs. the
limit of 4K.
*/
-#define TCOM_VENDOR_ID 0x10B7 /* 3Com's manufacturer's ID. */
+/* This table drives the PCI probe routines. It's mostly boilerplate in all
+ of the drivers, and will likely be provided by some future kernel.
+*/
+enum pci_flags_bit {
+ PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+ PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+};
+struct pci_id_info {
+ const char *name;
+ u16 vendor_id, device_id, device_id_mask, flags;
+ int drv_flags, io_size;
+ struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
+ long ioaddr, int irq, int chip_idx, int fnd_cnt);
+};
+
+enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4,
+ HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, };
+static struct device *vortex_probe1(int pci_bus, int pci_devfn,
+ struct device *dev, long ioaddr,
+ int irq, int dev_id, int card_idx);
+static struct pci_id_info pci_tbl[] = {
+ {"3c590 Vortex 10Mbps", 0x10B7, 0x5900, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+ {"3c595 Vortex 100baseTx", 0x10B7, 0x5950, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+ {"3c595 Vortex 100baseT4", 0x10B7, 0x5951, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+ {"3c595 Vortex 100base-MII", 0x10B7, 0x5952, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, vortex_probe1},
+ {"3Com Vortex", 0x10B7, 0x5900, 0xff00,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+ {"3c900 Boomerang 10baseT", 0x10B7, 0x9000, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+ {"3c900 Boomerang 10Mbps Combo", 0x10B7, 0x9001, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+ {"3c900 Cyclone 10Mbps Combo", 0x10B7, 0x9005, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+ {"3c900B-FL Cyclone 10base-FL", 0x10B7, 0x900A, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+ {"3c905 Boomerang 100baseTx", 0x10B7, 0x9050, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+ {"3c905 Boomerang 100baseT4", 0x10B7, 0x9051, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+ {"3c905B Cyclone 100baseTx", 0x10B7, 0x9055, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, vortex_probe1},
+ {"3c905B-FX Cyclone 100baseFx", 0x10B7, 0x905A, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+ {"3c980 Cyclone", 0x10B7, 0x9800, 0xfff0,
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, vortex_probe1},
+ {"3c575 Boomerang CardBus", 0x10B7, 0x5057, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+ {"3CCFE575 Cyclone CardBus", 0x10B7, 0x5157, 0xffff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS,
+ 128, vortex_probe1},
+ {"3c575 series CardBus (unknown version)", 0x10B7, 0x5057, 0xf0ff,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, vortex_probe1},
+ {"3Com Boomerang (unknown version)", 0x10B7, 0x9000, 0xff00,
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, vortex_probe1},
+ {0,}, /* 0 terminated list. */
+};
/* Operational definitions.
These are not used by other compilation units and thus are not
SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
SetTxThreshold = 18<<11, SetTxStart = 19<<11,
StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11,
- StatsDisable = 22<<11, StopCoax = 23<<11,};
+ StatsDisable = 22<<11, StopCoax = 23<<11, SetFilterBit = 25<<11,};
/* The SetRxFilter command accepts the following classes: */
enum RxFilter {
NodeAddr01=10, NodeAddr23=11, NodeAddr45=12,
DriverTune=13, Checksum=15};
+enum Window2 { /* Window 2. */
+ Wn2_ResetOptions=12,
+};
enum Window3 { /* Window 3: MAC/config bits. */
Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
};
union wn3_config {
int i;
struct w3_config_fields {
-#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2;
int pad8:8;
unsigned int ram_split:2, pad18:2, xcvr:4, autoselect:1;
int pad24:7;
-#elif defined(__BIG_ENDIAN_BITFIELD)
- unsigned int rom_size:2, ram_speed:2, ram_width:1, ram_size:3;
- int pad8:8;
- unsigned int xcvr:4, pad18:2, ram_split:2;
- int pad24:7;
- unsigned int autoselect:1;
-#else
-#error "Bitfield endianness not defined! Check your byteorder.h"
-#endif
} u;
};
enum ChipCaps { CapBusMaster=0x20 };
struct vortex_private {
- char devname[8]; /* "ethN" string, also for kernel debug. */
- const char *product_name;
- struct device *next_module;
- /* The Rx and Tx rings are here to keep them quad-word-aligned. */
+ /* The Rx and Tx rings should be quad-word-aligned. */
struct boom_rx_desc rx_ring[RX_RING_SIZE];
struct boom_tx_desc tx_ring[TX_RING_SIZE];
/* The addresses of transmit- and receive-in-place skbuffs. */
struct sk_buff* rx_skbuff[RX_RING_SIZE];
struct sk_buff* tx_skbuff[TX_RING_SIZE];
+ struct device *next_module;
+ void *priv_addr;
unsigned int cur_rx, cur_tx; /* The next free ring entry */
unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */
- struct enet_statistics stats;
+ struct net_device_stats stats;
struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */
/* PCI configuration space information. */
- u8 pci_bus, pci_dev_fn; /* PCI bus location, for power management. */
- u16 pci_device_id;
+ u8 pci_bus, pci_devfn; /* PCI bus location, for power management. */
+ char *cb_fn_base; /* CardBus function status addr space. */
+ int chip_id;
/* The remainder are related to chip state, mostly media selection. */
- int in_interrupt;
+ unsigned long in_interrupt;
struct timer_list timer; /* Media selection timer. */
int options; /* User-settable misc. driver options. */
- unsigned int
- media_override:3, /* Passed-in media type. */
- default_media:3, /* Read from the EEPROM/Wn3_Config. */
- full_duplex:1, autoselect:1,
- bus_master:1, /* Vortex can only do a fragment bus-m. */
- full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang */
- hw_csums:1, /* Has hardware checksums. */
- tx_full:1;
+ unsigned int media_override:3, /* Passed-in media type. */
+ default_media:4, /* Read from the EEPROM/Wn3_Config. */
+ full_duplex:1, force_fd:1, autoselect:1,
+ bus_master:1, /* Vortex can only do a fragment bus-m. */
+ full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang */
+ hw_csums:1, /* Has hardware checksums. */
+ tx_full:1;
u16 status_enable;
+ u16 intr_enable;
u16 available_media; /* From Wn3_Options. */
u16 capabilities, info1, info2; /* Various, from EEPROM. */
u16 advertising; /* NWay media advertisement */
{ "Default", 0, 0xFF, XCVR_10baseT, 10000},
};
-static int vortex_scan(struct device *dev);
-static struct device *vortex_found_device(struct device *dev, int ioaddr,
- int irq, int device_id,
- int options, int card_idx);
-static int vortex_probe1(struct device *dev);
-static int vortex_open(struct device *dev);
-static void mdio_sync(int ioaddr, int bits);
-static int mdio_read(int ioaddr, int phy_id, int location);
-#ifdef HAVE_PRIVATE_IOCTL
-static void mdio_write(int ioaddr, int phy_id, int location, int value);
+#ifndef CARDBUS
+static int vortex_scan(struct device *dev, struct pci_id_info pci_tbl[]);
#endif
+static int vortex_open(struct device *dev);
+static void mdio_sync(long ioaddr, int bits);
+static int mdio_read(long ioaddr, int phy_id, int location);
+static void mdio_write(long ioaddr, int phy_id, int location, int value);
static void vortex_timer(unsigned long arg);
static int vortex_start_xmit(struct sk_buff *skb, struct device *dev);
static int boomerang_start_xmit(struct sk_buff *skb, struct device *dev);
static int vortex_rx(struct device *dev);
static int boomerang_rx(struct device *dev);
-static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs);
+static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int vortex_close(struct device *dev);
-static void update_stats(int addr, struct device *dev);
-static struct enet_statistics *vortex_get_stats(struct device *dev);
+static void update_stats(long ioaddr, struct device *dev);
+static struct net_device_stats *vortex_get_stats(struct device *dev);
static void set_rx_mode(struct device *dev);
-#ifdef HAVE_PRIVATE_IOCTL
static int vortex_ioctl(struct device *dev, struct ifreq *rq, int cmd);
-#endif
-#ifndef NEW_MULTICAST
-static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
-#endif
\f
-/* Unlike the other PCI cards the 59x cards don't need a large contiguous
- memory region, so making the driver a loadable module is feasible.
-
- Unfortunately maximizing the shared code between the integrated and
- module version of the driver results in a complicated set of initialization
- procedures.
- init_module() -- modules / tc59x_init() -- built-in
- The wrappers for vortex_scan()
- vortex_scan() The common routine that scans for PCI and EISA cards
- vortex_found_device() Allocate a device structure when we find a card.
- Different versions exist for modules and built-in.
- vortex_probe1() Fill in the device structure -- this is separated
- so that the modules code can put it in dev->init.
-*/
/* This driver uses 'options' to pass the media type, full-duplex flag, etc. */
-/* Note: this is the only limit on the number of cards supported!! */
-static int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1,};
-static int full_duplex[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
+/* Option count limit only -- unlimited interfaces are supported. */
+#define MAX_UNITS 8
+static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1,};
+static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
/* A list of all installed Vortex devices, for removing the driver module. */
static struct device *root_vortex_dev = NULL;
#ifdef MODULE
+#ifndef CARDBUS
/* Variables to work-around the Compaq PCI BIOS32 problem. */
static int compaq_ioaddr = 0, compaq_irq = 0, compaq_device_id = 0x5900;
-
-static int debug = -1;
+#endif
#ifdef CARDBUS
static dev_node_t *vortex_attach(dev_locator_t *loc)
{
- u16 dev_id;
+ u16 dev_id, vendor_id;
u32 io;
u8 bus, devfn, irq;
struct device *dev;
+ int chip_idx;
if (loc->bus != LOC_PCI) return NULL;
bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
- printk(KERN_INFO "vortex_attach(bus %d, function %d)\n", bus, devfn);
pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
+ pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id);
pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+ printk(KERN_INFO "vortex_attach(bus %d, function %d, device %4.4x)\n",
+ bus, devfn, dev_id);
io &= ~3;
- dev = vortex_found_device(NULL, io, irq, dev_id, 0, -1);
+ if (io == 0 || irq == 0) {
+ printk(KERN_ERR "The 3Com CardBus Ethernet interface was not "
+ "assigned an %s.\n" KERN_ERR " It will not be activated.\n",
+ io == 0 ? "I/O address" : "IRQ");
+ return NULL;
+ }
+ for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
+ if (vendor_id == pci_tbl[chip_idx].vendor_id
+ && (dev_id & pci_tbl[chip_idx].device_id_mask) ==
+ pci_tbl[chip_idx].device_id)
+ break;
+ if (pci_tbl[chip_idx].vendor_id == 0) { /* Compiled out! */
+ printk(KERN_INFO "Unable to match chip type %4.4x %4.4x in "
+ "vortex_attach().\n", vendor_id, dev_id);
+ return NULL;
+ }
+ dev = vortex_probe1(bus, devfn, NULL, io, irq, chip_idx, MAX_UNITS+1);
if (dev) {
dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
strcpy(node->dev_name, dev->name);
}
if (*devp) {
struct device *dev = *devp;
+ struct vortex_private *vp = dev->priv;
if (dev->flags & IFF_UP)
vortex_close(dev);
dev->flags &= ~(IFF_UP|IFF_RUNNING);
unregister_netdev(dev);
+ if (vp->cb_fn_base) iounmap(vp->cb_fn_base);
kfree(dev);
*devp = *next;
+ kfree(vp);
kfree(node);
MOD_DEC_USE_COUNT;
}
}
struct driver_operations vortex_ops = {
- "3c59x_cb", vortex_attach, NULL, NULL, vortex_detach
+ "3c575_cb", vortex_attach, NULL, NULL, vortex_detach
};
#endif /* Cardbus support */
-int
-init_module(void)
+int init_module(void)
{
- if (debug >= 0)
- vortex_debug = debug;
if (vortex_debug)
- printk(version);
-
- root_vortex_dev = NULL;
+ printk(KERN_INFO "%s", version);
#ifdef CARDBUS
register_driver(&vortex_ops);
return 0;
#else
- {
- int cards_found = vortex_scan(0);
- if (cards_found == 0)
- printk("No 3Com Vortex/Boomerang cards found.\n");
- return cards_found ? 0 : -ENODEV;
- }
+ return vortex_scan(0, pci_tbl);
#endif
}
#else
int tc59x_probe(struct device *dev)
{
- int cards_found = 0;
-
- cards_found = vortex_scan(dev);
-
- if (vortex_debug > 0 && cards_found)
- printk(version);
-
- return cards_found ? 0 : -ENODEV;
+ static int scanned=0;
+ if(scanned++)
+ return -ENODEV;
+ printk(KERN_INFO "%s", version);
+ return vortex_scan(dev, pci_tbl);
}
#endif /* not MODULE */
-static int vortex_scan(struct device *dev)
+#ifndef CARDBUS
+static int vortex_scan(struct device *dev, struct pci_id_info pci_tbl[])
{
int cards_found = 0;
unsigned char pci_bus, pci_device_fn;
for (;pci_index < 0xff; pci_index++) {
- u8 pci_latency;
- u16 pci_command, new_command, vendor, device;
- int irq;
+ u16 vendor, device, pci_command, new_command, pwr_cmd;
+ int chip_idx, irq;
long ioaddr;
- if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
- pci_index, &pci_bus, &pci_device_fn)
+ if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8, pci_index,
+ &pci_bus, &pci_device_fn)
!= PCIBIOS_SUCCESSFUL)
break;
pcibios_read_config_word(pci_bus, pci_device_fn,
PCI_VENDOR_ID, &vendor);
pcibios_read_config_word(pci_bus, pci_device_fn,
PCI_DEVICE_ID, &device);
- pcibios_read_config_word(pci_bus, pci_device_fn,
- PCI_COMMAND, &pci_command);
+ for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
+ if (vendor == pci_tbl[chip_idx].vendor_id
+ && (device & pci_tbl[chip_idx].device_id_mask) ==
+ pci_tbl[chip_idx].device_id)
+ break;
+ if (pci_tbl[chip_idx].vendor_id == 0) /* Compiled out! */
+ continue;
+
{
#if LINUX_VERSION_CODE >= 0x20155
struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn);
- ioaddr = pdev->base_address[0];
+ ioaddr = pdev->base_address[0] & ~3;
irq = pdev->irq;
#else
u32 pci_ioaddr;
PCI_INTERRUPT_LINE, &pci_irq_line);
pcibios_read_config_dword(pci_bus, pci_device_fn,
PCI_BASE_ADDRESS_0, &pci_ioaddr);
- ioaddr = pci_ioaddr;
+ ioaddr = pci_ioaddr & ~3;;
irq = pci_irq_line;
#endif
}
- /* Remove I/O space marker in bit 0. */
- ioaddr &= ~3;
- if (vendor != TCOM_VENDOR_ID)
- continue;
+ /* Power-up the card. */
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ 0xe0, &pwr_cmd);
+ if (pwr_cmd & 0x3) {
+ /* Save the ioaddr and IRQ info! */
+ printk(KERN_INFO " A 3Com network adapter is powered down!"
+ " Setting the power state %4.4x->%4.4x.\n",
+ pwr_cmd, pwr_cmd & ~3);
+ pcibios_write_config_word(pci_bus, pci_device_fn,
+ 0xe0, pwr_cmd & ~3);
+ printk(KERN_INFO " Setting the IRQ to %d, IOADDR to %#lx.\n",
+ irq, ioaddr);
+ pcibios_write_config_byte(pci_bus, pci_device_fn,
+ PCI_INTERRUPT_LINE, irq);
+ pcibios_write_config_dword(pci_bus, pci_device_fn,
+ PCI_BASE_ADDRESS_0, ioaddr);
+ }
if (ioaddr == 0) {
printk(KERN_WARNING " A 3Com network adapter has been found, "
continue;
}
- if (check_region(ioaddr, VORTEX_TOTAL_SIZE))
+ if (check_region(ioaddr, pci_tbl[chip_idx].io_size))
continue;
/* Activate the card. */
+ pcibios_read_config_word(pci_bus, pci_device_fn,
+ PCI_COMMAND, &pci_command);
new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
if (pci_command != new_command) {
- printk(KERN_INFO " The PCI BIOS has not enabled this"
- " device! Updating PCI command %4.4x->%4.4x.\n",
- pci_command, new_command);
+ printk(KERN_INFO " The PCI BIOS has not enabled the device "
+ "at %d/%d. Updating PCI command %4.4x->%4.4x.\n",
+ pci_bus, pci_device_fn, pci_command, new_command);
pcibios_write_config_word(pci_bus, pci_device_fn,
PCI_COMMAND, new_command);
}
- dev = vortex_found_device(dev, ioaddr, irq,
- device, dev && dev->mem_start
- ? dev->mem_start : options[cards_found],
- cards_found);
+ dev = vortex_probe1(pci_bus, pci_device_fn, dev, ioaddr, irq,
+ chip_idx, cards_found);
if (dev) {
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
/* Get and check the latency values. On the 3c590 series
the latency timer must be set to the maximum value to avoid
data corruption that occurs when the timer expires during
a transfer -- a bug in the Vortex chip only. */
- u8 new_latency = (device&0xff00) == 0x5900 ? 248 : 32;
- vp->pci_bus = pci_bus;
- vp->pci_dev_fn = pci_device_fn;
- vp->pci_device_id = device;
+ u8 pci_latency;
+ u8 new_latency = (device & 0xff00) == 0x5900 ? 248 : 32;
pcibios_read_config_byte(pci_bus, pci_device_fn,
PCI_LATENCY_TIMER, &pci_latency);
/* Now check all slots of the EISA bus. */
if (EISA_bus) {
- static int ioaddr = 0x1000;
+ static long ioaddr = 0x1000;
for ( ; ioaddr < 0x9000; ioaddr += 0x1000) {
int device_id;
if (check_region(ioaddr, VORTEX_TOTAL_SIZE))
device_id = (inb(ioaddr + 0xC82)<<8) + inb(ioaddr + 0xC83);
if ((device_id & 0xFF00) != 0x5900)
continue;
- vortex_found_device(dev, ioaddr, inw(ioaddr + 0xC88) >> 12,
- device_id, dev && dev->mem_start
- ? dev->mem_start : options[cards_found],
- cards_found);
+ vortex_probe1(0, 0, dev, ioaddr, inw(ioaddr + 0xC88) >> 12,
+ 4, cards_found);
dev = 0;
cards_found++;
}
#ifdef MODULE
/* Special code to work-around the Compaq PCI BIOS32 problem. */
if (compaq_ioaddr) {
- vortex_found_device(dev, compaq_ioaddr, compaq_irq, compaq_device_id,
- dev && dev->mem_start ? dev->mem_start
- : options[cards_found], cards_found);
- cards_found++;
+ vortex_probe1(0, 0, dev, compaq_ioaddr, compaq_irq,
+ compaq_device_id, cards_found++);
dev = 0;
}
#endif
- /* 3c515 cards are now supported by the 3c515.c driver. */
-
- return cards_found;
+ return cards_found ? 0 : -ENODEV;
}
+#endif /* ! Cardbus */
-static struct device *
-vortex_found_device(struct device *dev, int ioaddr, int irq,
- int device_id, int option, int card_idx)
+static struct device *vortex_probe1(int pci_bus, int pci_devfn,
+ struct device *dev, long ioaddr,
+ int irq, int chip_idx, int card_idx)
{
struct vortex_private *vp;
- const char *product_name;
- int board_index = 0;
+ int option;
+ unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
+ int i;
- for (board_index = 0; product_ids[board_index]; board_index++) {
- if (device_id == product_ids[board_index])
- break;
- }
- /* Handle products we don't recognize, but might still work with. */
- if (product_ids[board_index])
- product_name = product_names[board_index];
- else if ((device_id & 0xff00) == 0x5900)
- product_name = "3c590 Vortex";
- else if ((device_id & 0xfff0) == 0x9000)
- product_name = "3c900";
- else if ((device_id & 0xfff0) == 0x9050)
- product_name = "3c905";
- else {
- printk(KERN_WARNING "Unknown 3Com PCI ethernet adapter type %4.4x detected:"
- " not configured.\n", device_id);
- return 0;
- }
+ dev = init_etherdev(dev, 0);
-#ifdef MODULE
- /* Allocate and fill new device structure. */
- {
- int dev_size = sizeof(struct device) +
- sizeof(struct vortex_private) + 15; /* Pad for alignment */
+ printk(KERN_INFO "%s: 3Com %s at 0x%lx, ",
+ dev->name, pci_tbl[chip_idx].name, ioaddr);
- dev = (struct device *) kmalloc(dev_size, GFP_KERNEL);
- memset(dev, 0, dev_size);
- }
- /* Align the Rx and Tx ring entries. */
- dev->priv = (void *)(((long)dev + sizeof(struct device) + 15) & ~15);
- vp = (struct vortex_private *)dev->priv;
- dev->name = vp->devname; /* An empty string. */
dev->base_addr = ioaddr;
dev->irq = irq;
- dev->init = vortex_probe1;
- vp->product_name = product_name;
- vp->options = option;
- if (card_idx >= 0) {
- if (full_duplex[card_idx] >= 0)
- vp->full_duplex = full_duplex[card_idx];
- } else
- vp->full_duplex = (option > 0 && (option & 0x10) ? 1 : 0);
+ dev->mtu = mtu;
- if (option > 0) {
- vp->media_override = ((option & 7) == XCVR_10baseTOnly) ?
- XCVR_10baseT : option & 7;
- vp->bus_master = (option & 16) ? 1 : 0;
- } else {
- vp->media_override = 7;
- vp->bus_master = 0;
+ /* Make certain the descriptor lists are aligned. */
+ {
+ void *mem = kmalloc(sizeof(*vp) + 15, GFP_KERNEL);
+ vp = (void *)(((long)mem + 15) & ~15);
+ vp->priv_addr = mem;
}
- ether_setup(dev);
+ memset(vp, 0, sizeof(*vp));
+ dev->priv = vp;
+
vp->next_module = root_vortex_dev;
root_vortex_dev = dev;
- if (register_netdev(dev) != 0)
- return 0;
-#else /* not a MODULE */
- if (dev) {
- /* Caution: quad-word alignment required for rings! */
- dev->priv = kmalloc(sizeof (struct vortex_private), GFP_KERNEL);
- memset(dev->priv, 0, sizeof (struct vortex_private));
- }
- dev = init_etherdev(dev, sizeof(struct vortex_private));
- dev->base_addr = ioaddr;
- dev->irq = irq;
- dev->mtu = mtu;
- vp = (struct vortex_private *)dev->priv;
- vp->product_name = product_name;
- vp->options = option;
+ vp->chip_id = chip_idx;
+ vp->pci_bus = pci_bus;
+ vp->pci_devfn = pci_devfn;
+
+ /* The lower four bits are the media type. */
+ if (dev->mem_start)
+ option = dev->mem_start;
+ else if (card_idx < MAX_UNITS)
+ option = options[card_idx];
+ else
+ option = -1;
+
if (option >= 0) {
vp->media_override = ((option & 7) == 2) ? 0 : option & 7;
vp->full_duplex = (option & 8) ? 1 : 0;
vp->full_duplex = 0;
vp->bus_master = 0;
}
+ if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
+ vp->full_duplex = 1;
- vortex_probe1(dev);
-#endif /* MODULE */
- return dev;
-}
-
-static int vortex_probe1(struct device *dev)
-{
- int ioaddr = dev->base_addr;
- struct vortex_private *vp = (struct vortex_private *)dev->priv;
- u16 *ether_addr = (u16 *)dev->dev_addr;
- unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
- int i;
-
- printk(KERN_INFO "%s: 3Com %s at %#3x,",
- dev->name, vp->product_name, ioaddr);
+ vp->force_fd = vp->full_duplex;
+ vp->options = option;
/* Read the station address from the EEPROM. */
EL3WINDOW(0);
printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
for (i = 0; i < 3; i++)
- ether_addr[i] = htons(eeprom[i + 10]);
+ ((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);
for (i = 0; i < 6; i++)
printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]);
+#ifdef __sparc__
+ printk(", IRQ %s\n", __irq_itoa(dev->irq));
+#else
printk(", IRQ %d\n", dev->irq);
/* Tell them about an invalid IRQ. */
if (vortex_debug && (dev->irq <= 0 || dev->irq >= NR_IRQS))
printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n",
dev->irq);
+#endif
+
+ if (pci_tbl[vp->chip_id].drv_flags & HAS_CB_FNS) {
+ u32 fn_st_addr; /* Cardbus function status space */
+ pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_2,
+ &fn_st_addr);
+ if (fn_st_addr)
+ vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128);
+ printk("%s: CardBus functions mapped %8.8x->%p (PCMCIA committee"
+ " brain-damage).\n", dev->name, fn_st_addr, vp->cb_fn_base);
+ EL3WINDOW(2);
+ outw(0x10 | inw(ioaddr + Wn2_ResetOptions), ioaddr + Wn2_ResetOptions);
+ }
/* Extract our information from the EEPROM data. */
vp->info1 = eeprom[13];
config.u.ram_width ? "word" : "byte",
ram_split[config.u.ram_split],
config.u.autoselect ? "autoselect/" : "",
- config.u.xcvr ? "NWay Autonegotiation" :
+ config.u.xcvr > XCVR_ExtMII ? "<invalid transceiver>" :
media_tbl[config.u.xcvr].name);
vp->default_media = config.u.xcvr;
vp->autoselect = config.u.autoselect;
} else
dev->if_port = vp->default_media;
- if (dev->if_port == XCVR_MII) {
+ if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
int phy, phy_idx = 0;
EL3WINDOW(4);
- for (phy = 0; phy < 32 && phy_idx < sizeof(vp->phys); phy++) {
- int mii_status;
- mdio_sync(ioaddr, 32);
- mii_status = mdio_read(ioaddr, phy, 1);
+ mii_preamble_required++;
+ mii_preamble_required++;
+ mdio_read(ioaddr, 24, 1);
+ for (phy = 1; phy <= 32 && phy_idx < sizeof(vp->phys); phy++) {
+ int mii_status, phyx = phy & 0x1f;
+ mii_status = mdio_read(ioaddr, phyx, 1);
if (mii_status && mii_status != 0xffff) {
- vp->phys[phy_idx++] = phy;
- printk(KERN_INFO " MII transceiver found at address %d, status %4x.\n",
- phy, mii_status);
- mdio_sync(ioaddr, 32);
- if ((mdio_read(ioaddr, phy, 1) & 0x0040) == 0)
- mii_preamble_required = 1;
+ vp->phys[phy_idx++] = phyx;
+ printk(KERN_INFO " MII transceiver found at address %d,"
+ " status %4x.\n", phyx, mii_status);
+ if ((mii_status & 0x0040) == 0)
+ mii_preamble_required++;
}
}
+ mii_preamble_required--;
if (phy_idx == 0) {
printk(KERN_WARNING" ***WARNING*** No MII transceivers found!\n");
vp->phys[0] = 24;
vp->advertising = mdio_read(ioaddr, vp->phys[0], 4);
if (vp->full_duplex) {
/* Only advertise the FD media types. */
- vp->advertising &= 0x015F;
+ vp->advertising &= ~0x02A0;
mdio_write(ioaddr, vp->phys[0], 4, vp->advertising);
}
}
}
/* We do a request_region() to register /proc/ioports info. */
- request_region(ioaddr, VORTEX_TOTAL_SIZE, vp->product_name);
+ request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name);
/* The 3c59x-specific entries in the device structure. */
dev->open = &vortex_open;
dev->hard_start_xmit = &vortex_start_xmit;
dev->stop = &vortex_close;
dev->get_stats = &vortex_get_stats;
-#ifdef HAVE_PRIVATE_IOCTL
dev->do_ioctl = &vortex_ioctl;
-#endif
-#ifdef NEW_MULTICAST
dev->set_multicast_list = &set_rx_mode;
-#else
- dev->set_multicast_list = &set_multicast_list;
-#endif
- return 0;
+ return dev;
}
\f
static int
vortex_open(struct device *dev)
{
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
struct vortex_private *vp = (struct vortex_private *)dev->priv;
union wn3_config config;
int i;
dev->name, vp->media_override,
media_tbl[vp->media_override].name);
dev->if_port = vp->media_override;
+ } else if (vp->autoselect && pci_tbl[vp->chip_id].drv_flags & HAS_NWAY) {
+ dev->if_port = XCVR_NWAY;
} else if (vp->autoselect) {
/* Find first available media type, starting with 100baseTx. */
dev->if_port = XCVR_100baseTx;
while (! (vp->available_media & media_tbl[dev->if_port].mask))
dev->if_port = media_tbl[dev->if_port].next;
-
- if (vortex_debug > 1)
- printk(KERN_DEBUG "%s: Initial media type %s.\n",
- dev->name, media_tbl[dev->if_port].name);
-
- init_timer(&vp->timer);
- vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
- vp->timer.data = (unsigned long)dev;
- vp->timer.function = &vortex_timer; /* timer handler */
- add_timer(&vp->timer);
} else
dev->if_port = vp->default_media;
+ init_timer(&vp->timer);
+ vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
+ vp->timer.data = (unsigned long)dev;
+ vp->timer.function = &vortex_timer; /* timer handler */
+ add_timer(&vp->timer);
+
+ if (vortex_debug > 1)
+ printk(KERN_DEBUG "%s: Initial media type %s.\n",
+ dev->name, media_tbl[dev->if_port].name);
+
+ vp->full_duplex = vp->force_fd;
config.u.xcvr = dev->if_port;
outl(config.i, ioaddr + Wn3_Config);
- if (dev->if_port == XCVR_MII) {
+ if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
int mii_reg1, mii_reg5;
EL3WINDOW(4);
/* Read BMSR (reg1) only to clear old status. */
outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
-#ifdef SA_SHIRQ
/* Use the now-standard shared IRQ implementation. */
if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ, dev->name, dev)) {
return -EAGAIN;
}
-#else
- if (dev->irq == 0 || irq2dev_map[dev->irq] != NULL)
- return -EAGAIN;
- irq2dev_map[dev->irq] = dev;
- if (request_irq(dev->irq, &vortex_interrupt, 0, vp->product_name)) {
- irq2dev_map[dev->irq] = NULL;
- return -EAGAIN;
- }
-#endif
if (vortex_debug > 1) {
EL3WINDOW(4);
if (dev->if_port == XCVR_10base2)
/* Start the thinnet transceiver. We should really wait 50ms...*/
outw(StartCoax, ioaddr + EL3_CMD);
- EL3WINDOW(4);
- outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |
- media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
+ if (dev->if_port != XCVR_NWAY) {
+ EL3WINDOW(4);
+ outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) |
+ media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
+ }
/* Switch to the stats window, and clear all stats by reading. */
outw(StatsDisable, ioaddr + EL3_CMD);
printk(KERN_DEBUG "%s: Filling in the Rx ring.\n", dev->name);
for (i = 0; i < RX_RING_SIZE; i++) {
struct sk_buff *skb;
- vp->rx_ring[i].next = virt_to_bus(&vp->rx_ring[i+1]);
+ vp->rx_ring[i].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[i+1]));
vp->rx_ring[i].status = 0; /* Clear complete bit. */
- vp->rx_ring[i].length = PKT_BUF_SZ | LAST_FRAG;
- skb = DEV_ALLOC_SKB(PKT_BUF_SZ);
+ vp->rx_ring[i].length = cpu_to_le32(PKT_BUF_SZ | LAST_FRAG);
+ skb = dev_alloc_skb(PKT_BUF_SZ);
vp->rx_skbuff[i] = skb;
if (skb == NULL)
break; /* Bad news! */
skb->dev = dev; /* Mark as being used by this device. */
#if LINUX_VERSION_CODE >= 0x10300
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- vp->rx_ring[i].addr = virt_to_bus(skb->tail);
+ vp->rx_ring[i].addr = cpu_to_le32(virt_to_bus(skb->tail));
#else
vp->rx_ring[i].addr = virt_to_bus(skb->data);
#endif
}
- vp->rx_ring[i-1].next = virt_to_bus(&vp->rx_ring[0]); /* Wrap the ring. */
+ /* Wrap the ring. */
+ vp->rx_ring[i-1].next = cpu_to_le32(virt_to_bus(&vp->rx_ring[0]));
outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr);
}
if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */
(vp->full_bus_master_tx ? DownComplete : TxAvailable) |
(vp->full_bus_master_rx ? UpComplete : RxComplete) |
(vp->bus_master ? DMADone : 0);
+ vp->intr_enable = SetIntrEnb | IntLatch | TxAvailable | RxComplete |
+ StatsFull | HostError | TxComplete | IntReq
+ | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete;
outw(vp->status_enable, ioaddr + EL3_CMD);
/* Ack all pending events, and set active indicator mask. */
outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
ioaddr + EL3_CMD);
- outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
- | HostError | TxComplete
- | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete,
- ioaddr + EL3_CMD);
+ outw(vp->intr_enable, ioaddr + EL3_CMD);
+ if (vp->cb_fn_base) /* The PCMCIA people are idiots. */
+ writel(0x8000, vp->cb_fn_base + 4);
MOD_INC_USE_COUNT;
static void vortex_timer(unsigned long data)
{
-#ifdef AUTOMEDIA
struct device *dev = (struct device *)data;
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
- unsigned long flags;
+ long ioaddr = dev->base_addr;
+ int next_tick = 0;
int ok = 0;
+ int media_status, mii_status, old_window;
if (vortex_debug > 1)
printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n",
dev->name, media_tbl[dev->if_port].name);
- save_flags(flags); cli(); {
- int old_window = inw(ioaddr + EL3_CMD) >> 13;
- int media_status;
- EL3WINDOW(4);
- media_status = inw(ioaddr + Wn4_Media);
- switch (dev->if_port) {
- case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx:
+ disable_irq(dev->irq);
+ old_window = inw(ioaddr + EL3_CMD) >> 13;
+ EL3WINDOW(4);
+ media_status = inw(ioaddr + Wn4_Media);
+ switch (dev->if_port) {
+ case XCVR_10baseT: case XCVR_100baseTx: case XCVR_100baseFx:
if (media_status & Media_LnkBeat) {
ok = 1;
if (vortex_debug > 1)
} else if (vortex_debug > 1)
printk(KERN_DEBUG "%s: Media %s is has no link beat, %x.\n",
dev->name, media_tbl[dev->if_port].name, media_status);
-
break;
- case XCVR_MII:
- {
- int mii_reg1 = mdio_read(ioaddr, vp->phys[0], 1);
+ case XCVR_MII: case XCVR_NWAY:
+ mii_status = mdio_read(ioaddr, vp->phys[0], 1);
+ ok = 1;
+ if (debug > 1)
+ printk(KERN_DEBUG "%s: MII transceiver has status %4.4x.\n",
+ dev->name, mii_status);
+ if (mii_status & 0x0004) {
int mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5);
- if (vortex_debug > 1)
- printk(KERN_DEBUG "%s: MII #%d status register is %4.4x, "
- "link partner capability %4.4x.\n",
- dev->name, vp->phys[0], mii_reg1, mii_reg5);
- if (mii_reg1 & 0x0004)
- ok = 1;
- break;
+ if (! vp->force_fd && mii_reg5 != 0xffff) {
+ int duplex = (mii_reg5&0x0100) ||
+ (mii_reg5 & 0x01C0) == 0x0040;
+ if (vp->full_duplex != duplex) {
+ vp->full_duplex = duplex;
+ printk(KERN_INFO "%s: Setting %s-duplex based on MII "
+ "#%d link partner capability of %4.4x.\n",
+ dev->name, vp->full_duplex ? "full" : "half",
+ vp->phys[0], mii_reg5);
+ /* Set the full-duplex bit. */
+ outb((vp->full_duplex ? 0x20 : 0) |
+ (dev->mtu > 1500 ? 0x40 : 0),
+ ioaddr + Wn3_MAC_Ctrl);
+ }
+ next_tick = 60*HZ;
+ }
}
+ break;
default: /* Other media types handled by Tx timeouts. */
if (vortex_debug > 1)
printk(KERN_DEBUG "%s: Media %s is has no indication, %x.\n",
dev->name, media_tbl[dev->if_port].name, media_status);
ok = 1;
- }
- if ( ! ok) {
+ }
+ if ( ! ok) {
union wn3_config config;
do {
printk(KERN_DEBUG "%s: Media selection failed, now trying "
"%s port.\n",
dev->name, media_tbl[dev->if_port].name);
- vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait);
- add_timer(&vp->timer);
+ next_tick = RUN_AT(media_tbl[dev->if_port].wait);
}
outw((media_status & ~(Media_10TP|Media_SQE)) |
media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
outw(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
ioaddr + EL3_CMD);
- }
- EL3WINDOW(old_window);
- } restore_flags(flags);
- if (vortex_debug > 1)
+ }
+ EL3WINDOW(old_window);
+ enable_irq(dev->irq);
+
+ if (vortex_debug > 2)
printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n",
dev->name, media_tbl[dev->if_port].name);
-#endif /* AUTOMEDIA*/
+ if (next_tick) {
+ vp->timer.expires = RUN_AT(next_tick);
+ add_timer(&vp->timer);
+ }
return;
}
static void vortex_tx_timeout(struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
int j;
printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
printk(KERN_ERR "%s: Interrupt posted but not delivered --"
" IRQ blocked by another device?\n", dev->name);
/* Bad idea here.. but we might as well handle a few events. */
- vortex_interrupt IRQ(dev->irq, dev, 0);
+ vortex_interrupt(dev->irq, dev, 0);
}
outw(TxReset, ioaddr + EL3_CMD);
for (j = 200; j >= 0 ; j--)
for (i = 0; i < TX_RING_SIZE; i++) {
printk(KERN_DEBUG " %d: @%p length %8.8x status %8.8x\n", i,
&vp->tx_ring[i],
- vp->tx_ring[i].length,
- vp->tx_ring[i].status);
+ le32_to_cpu(vp->tx_ring[i].length),
+ le32_to_cpu(vp->tx_ring[i].status));
}
}
#endif
}
/*
- * Handle uncommon interrupt sources. This is a seperate routine to minimize
+ * Handle uncommon interrupt sources. This is a separate routine to minimize
* the cache impact.
*/
static void
vortex_error(struct device *dev, int status)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
int do_tx_reset = 0;
int i;
DoneDidThat++;
}
}
- if (status & IntReq) /* Restore all interrupt sources. */
- outw(ioaddr + EL3_CMD, vp->status_enable);
+ if (status & IntReq) { /* Restore all interrupt sources. */
+ outw(vp->status_enable, ioaddr + EL3_CMD);
+ outw(vp->intr_enable, ioaddr + EL3_CMD);
+ }
if (status & HostError) {
u16 fifo_diag;
EL3WINDOW(4);
vortex_start_xmit(struct sk_buff *skb, struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
if (jiffies - dev->trans_start >= TX_TIMEOUT)
/* Put out the doubleword header... */
outl(skb->len, ioaddr + TX_FIFO);
-#ifdef VORTEX_BUS_MASTER
if (vp->bus_master) {
/* Set the bus-master controller to transfer the packet. */
outl(virt_to_bus(skb->data), ioaddr + Wn7_MasterAddr);
/* Interrupt us when the FIFO has room for max-sized packet. */
outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
}
-#else
- /* ... and the packet rounded to a doubleword. */
- outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
- DEV_FREE_SKB(skb);
- if (inw(ioaddr + TxFree) > 1536) {
- clear_bit(0, (void*)&dev->tbusy);
- } else
- /* Interrupt us when the FIFO has room for max-sized packet. */
- outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
-#endif /* bus master */
dev->trans_start = jiffies;
boomerang_start_xmit(struct sk_buff *skb, struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
if (jiffies - dev->trans_start >= TX_TIMEOUT)
printk(KERN_WARNING "%s: Tx Ring full, refusing to send buffer.\n",
dev->name);
return 1;
- }
- /* end change 06/25/97 M. Sievers */
+ }
vp->tx_skbuff[entry] = skb;
vp->tx_ring[entry].next = 0;
- vp->tx_ring[entry].addr = virt_to_bus(skb->data);
- vp->tx_ring[entry].length = skb->len | LAST_FRAG;
- vp->tx_ring[entry].status = skb->len | TxIntrUploaded;
+ vp->tx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->data));
+ vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG);
+ vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded);
save_flags(flags);
cli();
for (i = 600; i >= 0 ; i--)
if ( (inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0)
break;
- prev_entry->next = virt_to_bus(&vp->tx_ring[entry]);
+ prev_entry->next = cpu_to_le32(virt_to_bus(&vp->tx_ring[entry]));
if (inl(ioaddr + DownListPtr) == 0) {
outl(virt_to_bus(&vp->tx_ring[entry]), ioaddr + DownListPtr);
queued_packet++;
if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1)
vp->tx_full = 1;
else { /* Clear previous interrupt enable. */
- prev_entry->status &= ~TxIntrUploaded;
+ prev_entry->status &= cpu_to_le32(~TxIntrUploaded);
clear_bit(0, (void*)&dev->tbusy);
}
dev->trans_start = jiffies;
/* The interrupt handler does all of the Rx thread work and cleans up
after the Tx thread. */
-static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs)
+static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
-#ifdef SA_SHIRQ /* Use the now-standard shared IRQ implementation. */
struct device *dev = dev_id;
-#else
- struct device *dev = (struct device *)(irq2dev_map[irq]);
-#endif
- struct vortex_private *vp;
- int ioaddr, status;
- int latency;
+ struct vortex_private *vp = (struct vortex_private *)dev->priv;
+ long ioaddr;
+ int latency, status;
int work_done = max_interrupt_work;
- vp = (struct vortex_private *)dev->priv;
- if (test_and_set_bit(0, (void*)&vp->in_interrupt)) {
+#if defined(__i386__)
+ /* A lock to prevent simultaneous entry bug on Intel SMP machines. */
+ if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+ printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
+ dev->name);
+ dev->interrupt = 0; /* Avoid halting machine. */
+ return;
+ }
+#else
+ if (dev->interrupt) {
printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
return;
}
+ dev->interrupt = 1;
+#endif
dev->interrupt = 1;
ioaddr = dev->base_addr;
latency = inb(ioaddr + Timer);
-
status = inw(ioaddr + EL3_STATUS);
if (vortex_debug > 4)
mark_bh(NET_BH);
}
}
-#ifdef VORTEX_BUS_MASTER
if (status & DMADone) {
- outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
- clear_bit(0, (void*)&dev->tbusy);
- DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */
- mark_bh(NET_BH);
+ if (inw(ioaddr + Wn7_MasterStatus) & 0x1000) {
+ outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */
+ DEV_FREE_SKB(vp->tx_skb); /* Release the transfered buffer */
+ if (inw(ioaddr + TxFree) > 1536) {
+ clear_bit(0, (void*)&dev->tbusy);
+ mark_bh(NET_BH);
+ } else /* Interrupt when FIFO has room for max-sized packet. */
+ outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD);
+ }
}
-#endif
/* Check for all uncommon interrupts at once. */
- if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq))
+ if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) {
+ if (status == 0xffff)
+ break;
vortex_error(dev, status);
+ }
if (--work_done < 0) {
if ((status & (0x7fe - (UpComplete | DownComplete))) == 0) {
/* Disable all pending interrupts. */
outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
- /* Set a timer to reenable interrupts. */
-
+ /* The timer will reenable interrupts. */
break;
}
}
/* Acknowledge the IRQ. */
outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
+ if (vp->cb_fn_base) /* The PCMCIA people are idiots. */
+ writel(0x8000, vp->cb_fn_base + 4);
} while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
dev->name, status);
+#if defined(__i386__)
+ clear_bit(0, (void*)&dev->interrupt);
+#else
dev->interrupt = 0;
- clear_bit(0, (void*)&vp->in_interrupt);
+#endif
return;
}
-static int
-vortex_rx(struct device *dev)
+static int vortex_rx(struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
int i;
short rx_status;
int pkt_len = rx_status & 0x1fff;
struct sk_buff *skb;
- skb = DEV_ALLOC_SKB(pkt_len + 5);
+ skb = dev_alloc_skb(pkt_len + 5);
if (vortex_debug > 4)
printk(KERN_DEBUG "Receiving packet size %d status %4.4x.\n",
pkt_len, rx_status);
if (skb != NULL) {
skb->dev = dev;
-#if LINUX_VERSION_CODE >= 0x10300
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
/* 'skb_put()' points to the start of sk_buff data area. */
- insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
- (pkt_len + 3) >> 2);
+ if (vp->bus_master &&
+ ! (inw(ioaddr + Wn7_MasterStatus) & 0x8000)) {
+ outl(virt_to_bus(skb_put(skb, pkt_len)),
+ ioaddr + Wn7_MasterAddr);
+ outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen);
+ outw(StartDMAUp, ioaddr + EL3_CMD);
+ while (inw(ioaddr + Wn7_MasterStatus) & 0x8000)
+ ;
+ } else {
+ insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len),
+ (pkt_len + 3) >> 2);
+ }
outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
skb->protocol = eth_type_trans(skb, dev);
-#else
- skb->len = pkt_len;
- /* 'skb->data' points to the start of sk_buff data area. */
- insl(ioaddr + RX_FIFO, skb->data, (pkt_len + 3) >> 2);
- outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
-#endif /* KERNEL_1_3_0 */
netif_rx(skb);
dev->last_rx = jiffies;
vp->stats.rx_packets++;
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
int entry = vp->cur_rx % RX_RING_SIZE;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
int rx_status;
int rx_work_limit = vp->dirty_rx + RX_RING_SIZE - vp->cur_rx;
printk(KERN_DEBUG " In boomerang_rx(), status %4.4x, rx_status "
"%4.4x.\n",
inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));
- while ((--rx_work_limit >= 0) &&
- ((rx_status = vp->rx_ring[entry].status) & RxDComplete)) {
+ while ((rx_status = le32_to_cpu(vp->rx_ring[entry].status)) & RxDComplete){
+ if (--rx_work_limit < 0)
+ break;
if (rx_status & RxDError) { /* Error, update stats. */
unsigned char rx_error = rx_status >> 16;
if (vortex_debug > 2)
/* Check if the packet is long enough to just accept without
copying to a properly sized skbuff. */
if (pkt_len < rx_copybreak
- && (skb = DEV_ALLOC_SKB(pkt_len + 2)) != 0) {
+ && (skb = dev_alloc_skb(pkt_len + 2)) != 0) {
skb->dev = dev;
-#if LINUX_VERSION_CODE >= 0x10300
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
/* 'skb_put()' points to the start of sk_buff data area. */
memcpy(skb_put(skb, pkt_len),
- bus_to_virt(vp->rx_ring[entry].addr),
+ bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)),
pkt_len);
-#else
- memcpy(skb->data, bus_to_virt(vp->rx_ring[entry].addr), pkt_len);
- skb->len = pkt_len;
-#endif
rx_copy++;
- } else{
+ } else {
void *temp;
/* Pass up the skbuff already on the Rx ring. */
skb = vp->rx_skbuff[entry];
- if (skb == NULL) {
- printk(KERN_WARNING "%s: in boomerang_rx -- attempt to use NULL skb caught\n", dev->name);
- break;
- }
vp->rx_skbuff[entry] = NULL;
-#if LINUX_VERSION_CODE >= 0x10300
temp = skb_put(skb, pkt_len);
-#else
- temp = skb->data;
-#endif
/* Remove this checking code for final release. */
- if (bus_to_virt(vp->rx_ring[entry].addr) != temp)
+ if (bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)) != temp)
printk(KERN_ERR "%s: Warning -- the skbuff addresses do not match"
" in boomerang_rx: %p vs. %p.\n", dev->name,
- bus_to_virt(vp->rx_ring[entry].addr), temp);
+ bus_to_virt(le32_to_cpu(vp->rx_ring[entry].addr)),
+ temp);
rx_nocopy++;
}
-#if LINUX_VERSION_CODE > 0x10300
skb->protocol = eth_type_trans(skb, dev);
{ /* Use hardware checksum info. */
int csum_bits = rx_status & 0xee000000;
rx_csumhits++;
}
}
-#else
- skb->len = pkt_len;
-#endif
netif_rx(skb);
dev->last_rx = jiffies;
vp->stats.rx_packets++;
struct sk_buff *skb;
entry = vp->dirty_rx % RX_RING_SIZE;
if (vp->rx_skbuff[entry] == NULL) {
- skb = DEV_ALLOC_SKB(PKT_BUF_SZ);
- if (skb == NULL) {
- printk(KERN_DEBUG "%s: in boomerang_rx -- could not allocate skbuff\n", dev->name);
+ skb = dev_alloc_skb(PKT_BUF_SZ);
+ if (skb == NULL)
break; /* Bad news! */
- }
skb->dev = dev; /* Mark as being used by this device. */
-#if LINUX_VERSION_CODE > 0x10300
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- vp->rx_ring[entry].addr = virt_to_bus(skb->tail);
-#else
- vp->rx_ring[entry].addr = virt_to_bus(skb->data);
-#endif
+ vp->rx_ring[entry].addr = cpu_to_le32(virt_to_bus(skb->tail));
vp->rx_skbuff[entry] = skb;
}
vp->rx_ring[entry].status = 0; /* Clear complete bit. */
outw(UpUnstall, ioaddr + EL3_CMD);
}
-
- if (vp->dirty_rx >= RX_RING_SIZE ) {
- vp->cur_rx -= RX_RING_SIZE;
- vp->dirty_rx -= RX_RING_SIZE;
- }
-
return 0;
}
vortex_close(struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
int i;
dev->start = 0;
/* Turn off thinnet power. Green! */
outw(StopCoax, ioaddr + EL3_CMD);
-#ifdef SA_SHIRQ
free_irq(dev->irq, dev);
-#else
- free_irq(dev->irq);
- irq2dev_map[dev->irq] = 0;
-#endif
outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
return 0;
}
-static struct enet_statistics *
-vortex_get_stats(struct device *dev)
+static struct net_device_stats *vortex_get_stats(struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
unsigned long flags;
table. This is done by checking that the ASM (!) code generated uses
atomic updates with '+='.
*/
-static void update_stats(int ioaddr, struct device *dev)
+static void update_stats(long ioaddr, struct device *dev)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
return;
}
-#ifdef HAVE_PRIVATE_IOCTL
static int vortex_ioctl(struct device *dev, struct ifreq *rq, int cmd)
{
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
u16 *data = (u16 *)&rq->ifr_data;
int phy = vp->phys[0] & 0x1f;
- if (vortex_debug > 2)
- printk(KERN_DEBUG "%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n",
- dev->name, rq->ifr_ifrn.ifrn_name, cmd,
- data[0], data[1], data[2], data[3]);
-
- switch(cmd) {
+ switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
data[0] = phy;
case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
case SIOCDEVPRIVATE+2: /* Write the specified MII register */
if (!suser())
return -EPERM;
+ EL3WINDOW(4);
mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
return 0;
default:
return -EOPNOTSUPP;
}
}
-#endif /* HAVE_PRIVATE_IOCTL */
-/* This new version of set_rx_mode() supports v1.4 kernels.
- The Vortex chip has no documented multicast filter, so the only
+/* Pre-Cyclone chips have no documented multicast filter, so the only
multicast setting is to receive all multicast frames. At least
the chip has a very clean way to set the mode, unlike many others. */
-static void
-set_rx_mode(struct device *dev)
+static void set_rx_mode(struct device *dev)
{
- int ioaddr = dev->base_addr;
+ long ioaddr = dev->base_addr;
int new_mode;
if (dev->flags & IFF_PROMISC) {
outw(new_mode, ioaddr + EL3_CMD);
}
-#ifndef NEW_MULTICAST
-/* The old interface to set the Rx mode. */
-static void
-set_multicast_list(struct device *dev, int num_addrs, void *addrs)
-{
- set_rx_mode(dev);
-}
-#endif
\f
/* MII transceiver control section.
/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually
met by back-to-back PCI I/O cycles, but we insert a delay to avoid
"overclocking" issues. */
-#define mdio_delay() udelay(1)
+#define mdio_delay() inl(mdio_addr)
#define MDIO_SHIFT_CLK 0x01
#define MDIO_DIR_WRITE 0x04
/* Generate the preamble required for initial synchronization and
a few older transceivers. */
-static void mdio_sync(int ioaddr, int bits)
+static void mdio_sync(long ioaddr, int bits)
{
- int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
- /* Establish sync by sending at least 32 logic ones. */
+ /* Establish sync by sending at least 32 logic ones. */
while (-- bits >= 0) {
outw(MDIO_DATA_WRITE1, mdio_addr);
mdio_delay();
}
}
-static int mdio_read(int ioaddr, int phy_id, int location)
+static int mdio_read(long ioaddr, int phy_id, int location)
{
int i;
int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
unsigned int retval = 0;
- int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
if (mii_preamble_required)
mdio_sync(ioaddr, 32);
outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
- return retval>>1 & 0xffff;
+#if 0
+ return (retval>>1) & 0x1ffff;
+#else
+ return retval & 0x20000 ? 0xffff : retval>>1 & 0xffff;
+#endif
}
-static void mdio_write(int ioaddr, int phy_id, int location, int value)
+static void mdio_write(long ioaddr, int phy_id, int location, int value)
{
int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
- int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ long mdio_addr = ioaddr + Wn4_PhysicalMgmt;
int i;
if (mii_preamble_required)
\f
#ifdef MODULE
-void
-cleanup_module(void)
+void cleanup_module(void)
{
struct device *next_dev;
/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
while (root_vortex_dev) {
- next_dev = ((struct vortex_private *)root_vortex_dev->priv)->next_module;
+ struct vortex_private *vp=(void *)(root_vortex_dev->priv);
+ next_dev = vp->next_module;
unregister_netdev(root_vortex_dev);
outw(TotalReset, root_vortex_dev->base_addr + EL3_CMD);
- release_region(root_vortex_dev->base_addr, VORTEX_TOTAL_SIZE);
+ release_region(root_vortex_dev->base_addr,
+ pci_tbl[vp->chip_id].io_size);
kfree(root_vortex_dev);
+ kfree(vp->priv_addr);
root_vortex_dev = next_dev;
}
}
* Local variables:
* compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
* SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c"
- * compile-command-alt1: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c -o 3c59x_cb.o"
+ * cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c59x.c -o 3c575_cb.o -I/usr/src/pcmcia-cs-3.0.5/include/"
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 4
#endif
/*
- * Define various macros for Channel Attention, word swapping etc., dependant
+ * Define various macros for Channel Attention, word swapping etc., dependent
* on architecture. MVME and BVME are 680x0 based, otherwise it is Intel.
*/
#ifdef MODULE
+EXPORT_SYMBOL(ei_open);
+EXPORT_SYMBOL(ei_close);
+EXPORT_SYMBOL(ei_interrupt);
+EXPORT_SYMBOL(ethdev_init);
+EXPORT_SYMBOL(NS8390_init);
+
struct module *NS8390_module = NULL;
int init_module(void)
L_OBJS += 8390.o
else
ifdef CONFIG_8390_MODULE
- M_OBJS += 8390.o
+ MX_OBJS += 8390.o
endif
endif
* Thanks to Alteon and 3Com for providing hardware and documentation
* enabling me to write this driver.
*
+ * A mailing list for discussing the use of this driver has been
+ * setup, please subscribe to the lists if you have any questions
+ * about the driver. Send mail to linux-acenic-help@sunsite.auc.dk to
+ * see how to subscribe.
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* firmware. Also the programming interface is quite neat, except for
* the parts dealing with the i2c eeprom on the card ;-)
*
- * A number of standard Ethernet receive skb's are now allocated at
- * init time and not released before the driver is unloaded. This
- * makes it possible to do ifconfig down/up.
- *
* Using jumbo frames:
*
* To enable jumbo frames, simply specify an mtu between 1500 and 9000
static int max_tx_desc[8] = {0, };
static int max_rx_desc[8] = {0, };
-static const char *version = "acenic.c: v0.19 12/17/98 Jes Sorensen (Jes.Sorensen@cern.ch)\n";
+static const char *version = "acenic.c: v0.22 01/07/99 Jes Sorensen (Jes.Sorensen@cern.ch)\n";
static struct device *root_dev = NULL;
static int i = 0;
int boards_found = 0;
int version_disp;
- u32 tmp;
struct ace_private *ap;
+ u8 pci_latency;
+#if 0
u16 vendor, device;
u8 pci_bus;
u8 pci_dev_fun;
- u8 pci_latency;
u8 irq;
+#endif
+ struct pci_dev *pdev = NULL;
if (!pci_present()) /* is PCI support present? */
return -ENODEV;
version_disp = 0;
- for (; i < 255; i++)
+ while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev)))
{
dev = NULL;
- if (pcibios_find_class(PCI_CLASS_NETWORK_ETHERNET << 8,
- i, &pci_bus, &pci_dev_fun) !=
- PCIBIOS_SUCCESSFUL)
- break;
-
- pcibios_read_config_word(pci_bus, pci_dev_fun,
- PCI_VENDOR_ID, &vendor);
-
- pcibios_read_config_word(pci_bus, pci_dev_fun,
- PCI_DEVICE_ID, &device);
-
- if ((vendor != PCI_VENDOR_ID_ALTEON) &&
- !((vendor == PCI_VENDOR_ID_3COM) &&
- (device == PCI_DEVICE_ID_3COM_3C985)))
+ if ((pdev->vendor != PCI_VENDOR_ID_ALTEON) &&
+ !((pdev->vendor == PCI_VENDOR_ID_3COM) &&
+ (pdev->device == PCI_DEVICE_ID_3COM_3C985)))
continue;
dev = init_etherdev(dev, sizeof(struct ace_private));
dev->priv = kmalloc(sizeof(*ap), GFP_KERNEL);
ap = dev->priv;
- ap->vendor = vendor;
-
- /* Read register base address from
- PCI Configuration Space */
+ ap->pdev = pdev;
+ ap->vendor = pdev->vendor;
- pcibios_read_config_dword(pci_bus, pci_dev_fun,
- PCI_BASE_ADDRESS_0, &tmp);
+ pci_set_master(pdev);
- pcibios_read_config_byte(pci_bus, pci_dev_fun,
- PCI_INTERRUPT_LINE, &irq);
-
- pcibios_read_config_word(pci_bus, pci_dev_fun,
- PCI_COMMAND, &ap->pci_command);
-
- if (!(ap->pci_command & PCI_COMMAND_MASTER)){
- ap->pci_command |= PCI_COMMAND_MASTER;
-
- pcibios_write_config_word(pci_bus, pci_dev_fun,
- PCI_COMMAND,
- ap->pci_command);
- }
-
- if (!(ap->pci_command & PCI_COMMAND_MEMORY)){
- printk(KERN_ERR "Shared mem not enabled - "
- "unable to configure AceNIC\n");
- break;
- }
-
- dev->irq = irq;
- ap->pci_bus = pci_bus;
- ap->pci_dev_fun = pci_dev_fun;
+ dev->irq = pdev->irq;
#ifdef __SMP__
spin_lock_init(&ap->lock);
#endif
printk(version);
}
- pcibios_read_config_byte(pci_bus, pci_dev_fun,
- PCI_LATENCY_TIMER, &pci_latency);
+ pci_read_config_word(pdev, PCI_COMMAND, &ap->pci_command);
+
+ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency <= 0x40){
pci_latency = 0x40;
- pcibios_write_config_byte(pci_bus, pci_dev_fun,
- PCI_LATENCY_TIMER,
- pci_latency);
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER,
+ pci_latency);
}
switch(ap->vendor){
printk(KERN_INFO "%s: Unknown AceNIC ", dev->name);
break;
}
- printk("Gigabit Ethernet at 0x%08x, irq %i, PCI latency %i "
- "clks\n", tmp, dev->irq, pci_latency);
+ printk("Gigabit Ethernet at 0x%08lx, irq %i, PCI latency %i "
+ "clks\n", pdev->base_address[0], dev->irq, pci_latency);
/*
* Remap the regs into kernel space.
*/
- ap->regs = (struct ace_regs *)ioremap(tmp, 0x4000);
+ ap->regs = (struct ace_regs *)ioremap(pdev->base_address[0],
+ 0x4000);
if (!ap->regs){
printk(KERN_ERR "%s: Unable to map I/O register, "
"AceNIC %i will be disabled.\n", dev->name, i);
struct ace_private *ap;
struct ace_regs *regs;
struct ace_info *info;
- u32 tig_ver, mac1 = 0, mac2 = 0, tmp;
+ u32 tig_ver, mac1, mac2, tmp;
unsigned long tmp_ptr, myjif;
short i;
return -ENODEV;
}
+ mac1 = 0;
for(i = 0; i < 4; i++){
mac1 = mac1 << 8;
mac1 |= read_eeprom_byte(regs, 0x8c+i);
}
+ mac2 = 0;
for(i = 4; i < 8; i++){
mac2 = mac2 << 8;
mac2 |= read_eeprom_byte(regs, 0x8c+i);
"supported, PCI write and invalidate "
"disabled\n", L1_CACHE_BYTES);
ap->pci_command &= ~PCI_COMMAND_INVALIDATE;
- pcibios_write_config_word(ap->pci_bus,
- ap->pci_dev_fun,
- PCI_COMMAND,
- ap->pci_command);
+ pci_write_config_word(ap->pdev, PCI_COMMAND,
+ ap->pci_command);
}
}
}
#if 0
{
u32 tmp;
- tmp = regs->AssistState;
- tmp &= ~2;
- tmp |= 1;
- regs->AssistState = tmp;
tmp = regs->MacRxState;
tmp &= ~4;
regs->TuneStatTicks = 2 * TICKS_PER_SEC;
- if ((board_idx < 8) && tx_coal_tick[board_idx])
- regs->TuneTxCoalTicks = tx_coal_tick[board_idx] *
- TICKS_PER_SEC / 1000;
- else
+ if (board_idx >= 0) {
+ if ((board_idx < 8) && tx_coal_tick[board_idx])
+ regs->TuneTxCoalTicks = tx_coal_tick[board_idx] *
+ TICKS_PER_SEC / 1000;
+ else
+ regs->TuneTxCoalTicks = TICKS_PER_SEC / 500;
+ if ((board_idx < 8) && max_tx_desc[board_idx])
+ regs->TuneMaxTxDesc = max_tx_desc[board_idx];
+ else
+ regs->TuneMaxTxDesc = 7;
+
+ if ((board_idx < 8) && rx_coal_tick[board_idx])
+ regs->TuneRxCoalTicks = rx_coal_tick[board_idx] *
+ TICKS_PER_SEC / 1000;
+ else
+ regs->TuneRxCoalTicks = TICKS_PER_SEC / 10000;
+ if ((board_idx < 8) && max_rx_desc[board_idx])
+ regs->TuneMaxRxDesc = max_rx_desc[board_idx];
+ else
+ regs->TuneMaxRxDesc = 2;
+
+ if (board_idx < 8)
+ regs->TuneTrace = trace[board_idx];
+ else
+ regs->TuneTrace = 0;
+ }else{
regs->TuneTxCoalTicks = TICKS_PER_SEC / 500;
- if ((board_idx < 8) && max_tx_desc[board_idx])
- regs->TuneMaxTxDesc = max_tx_desc[board_idx];
- else
regs->TuneMaxTxDesc = 7;
-
- if ((board_idx < 8) && rx_coal_tick[board_idx])
- regs->TuneRxCoalTicks = rx_coal_tick[board_idx] *
- TICKS_PER_SEC / 1000;
- else
regs->TuneRxCoalTicks = TICKS_PER_SEC / 10000;
- if ((board_idx < 8) && max_rx_desc[board_idx])
- regs->TuneMaxRxDesc = max_rx_desc[board_idx];
- else
regs->TuneMaxRxDesc = 2;
-
- if (board_idx < 8)
- regs->TuneTrace = trace[board_idx];
- else
regs->TuneTrace = 0;
+ }
tmp = LNK_ENABLE;
- if ((board_idx > 7) || !(link[board_idx])){
- if (board_idx > 8)
+ if ((board_idx > 7) || (board_idx < 0) || !(link[board_idx])){
+ if (board_idx > 7)
printk(KERN_WARNING "%s: more then 8 NICs detected, "
"ignoring link options!\n", dev->name);
/*
tmp |= LNK_TX_FLOW_CTL_Y;
} else {
int option = link[board_idx];
+
if (option & 0x01){
printk(KERN_INFO "%s: Setting half duplex link\n",
dev->name);
myjif = jiffies + 3 * HZ;
while (time_before(jiffies, myjif) && !ap->fw_running);
if (!ap->fw_running){
- printk(KERN_ERR "%s: firmware NOT running!\n", dev->name);
+ printk(KERN_ERR "%s: Firmware NOT running!\n", dev->name);
ace_dump_trace(ap);
regs->CpuCtrl |= CPU_HALT;
return -EBUSY;
}
-__initfunc(int ace_copy(struct ace_regs *regs, void *src, u32 dest, int size))
+__initfunc(void ace_copy(struct ace_regs *regs, void *src, u32 dest, int size))
{
int tsize;
u32 tdest;
+ if (size <= 0)
+ return;
+
while(size > 0){
tsize = min(((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
min(size, ACE_WINDOW_SIZE));
size -= tsize;
}
- return 0;
+ return;
}
-__initfunc(int ace_clear(struct ace_regs *regs, u32 dest, int size))
+__initfunc(void ace_clear(struct ace_regs *regs, u32 dest, int size))
{
- int tsize;
+ int tsize = 0;
u32 tdest;
+ if (size <= 0)
+ return;
+
while(size > 0){
tsize = min(((~dest & (ACE_WINDOW_SIZE - 1)) + 1),
min(size, ACE_WINDOW_SIZE));
size -= tsize;
}
- return 0;
+ return;
}
int flags;
u16 vendor;
u16 pci_command;
+ struct pci_dev *pdev;
+#if 0
u8 pci_bus;
u8 pci_dev_fun;
+#endif
char name[24];
struct net_device_stats stats;
};
0x3c010001, 0x220821, 0xac317120, 0x8fbf0024, 0x8fb40020, 0x8fb3001c,
0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, 0x0,
0x0 };
-u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __init = {
+u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = {
0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x416c7465, 0x6f6e2041,
0x63654e49, 0x43205600, 0x42424242, 0x0, 0x0, 0x0,
0x135430, 0x13e7fc, 0x0, 0x0, 0x0, 0x0,
0x12000060, 0x12000180, 0x120001e0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x30001, 0x1,
0x30201, 0x0, 0x0 };
-u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __init = {
+u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73,
0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 0x6f6e2f66, 0x776d6169,
0x6e2e632c, 0x7620312e, 0x312e322e, 0x31312031, 0x3939382f, 0x30342f32,
int tigon2FwBssLen = 0x20c0;
u32 tigon2FwSbssAddr = 0x134a0;
int tigon2FwSbssLen = 0xa8;
-u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __init = {
+u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = {
0x0, 0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001,
0x8fbd3380, 0x3a0f021, 0x3c100000, 0x26104000, 0xc0010c0, 0x0,
0xd, 0x3c1d0001, 0x8fbd3384, 0x3a0f021, 0x3c100000, 0x26104000,
0xaf820044, 0x8f820044, 0x451024, 0xaf820044, 0x24630001, 0x28620008,
0x5440ffee, 0x641007, 0x3e00008, 0x0, 0x0, 0x0,
0x0 };
-u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __init = {
+u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __initdata = {
0x1, 0x1, 0x1, 0xc001fc, 0x3ffc, 0xc00000,
0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x0, 0x0,
0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242, 0x0,
0x12000060, 0x12000180, 0x120001e0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x30001, 0x1,
0x30201, 0x0, 0x0 };
-u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __init = {
+u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = {
0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73,
0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x66776d61,
0x696e2e63, 0x2c762031, 0x2e312e34, 0x372e3420, 0x31393938, 0x2f31302f,
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/amigaints.h>
+#include <asm/amigahw.h>
#include "8390.h"
unsigned int key = ((struct ei_device *)ariadne2_dev.priv)->priv;
free_irq(IRQ_AMIGA_PORTS, &ariadne2_dev);
unregister_netdev(&ariadne2_dev);
- zorro_config_board(key, 0);
+ zorro_unconfig_board(key, 0);
unlock_8390_module();
}
{
struct net_local *lp = dev_at1700.priv;
unregister_netdev(&dev_at1700);
+#ifdef CONFIG_MCA
if(lp->mca_slot)
{
mca_mark_as_unused(lp->mca_slot);
}
+#endif
kfree(dev_at1700.priv);
dev_at1700.priv = NULL;
/* Same on both card types */
#define COPS_CLEAR_INT 1
-/* LAP response codes recieved from the cards. */
+/* LAP response codes received from the cards. */
#define LAP_INIT 1 /* Init cmd */
#define LAP_INIT_RSP 2 /* Init response */
#define LAP_WRITE 3 /* Write cmd */
/* cmd halfword values */
#define I596_SCB_ACK 0xF000 /* ACKNOWLEDGMENTS */
#define I596_SCB_ACK_CX 0x8000 /* Ack command completion */
-#define I596_SCB_ACK_FR 0x4000 /* Ack recieved frame */
+#define I596_SCB_ACK_FR 0x4000 /* Ack received frame */
#define I596_SCB_ACK_CNA 0x2000 /* Ack command unit not active */
#define I596_SCB_ACK_RNR 0x1000 /* Ack rcv unit not ready */
#define I596_SCB_ACK_ALL 0xF000 /* Ack everything */
/* status halfword values */
#define I596_SCB_STAT 0xF000 /* STATUS */
#define I596_SCB_CX 0x8000 /* command completion */
-#define I596_SCB_FR 0x4000 /* recieved frame */
+#define I596_SCB_FR 0x4000 /* received frame */
#define I596_SCB_CNA 0x2000 /* command unit not active */
#define I596_SCB_RNR 0x1000 /* rcv unit not ready */
This is a compatibility hardware problem.
Versions:
- 0.11b Pascal Dupuis : works as a module under 2.1.xx
- debug messages are flagged as KERN_DEBUG to avoid console
- flooding
- added locking at critical parts
+ 0.11d added __initdata, __initfunc stuff; call spin_lock_init
+ in eepro_probe1. Replaced "eepro" by dev->name. Augmented
+ the code protected by spin_lock in interrupt routine
+ (PdP, 12/12/1998)
+ 0.11c minor cleanup (PdP, RMC, 09/12/1998)
+ 0.11b Pascal Dupuis (dupuis@lei.ucl.ac.be): works as a module
+ under 2.1.xx. Debug messages are flagged as KERN_DEBUG to
+ avoid console flooding. Added locking at critical parts. Now
+ the dawn thing is SMP safe.
0.11a Attempt to get 2.1.xx support up (RMC)
0.11 Brian Candler added support for multiple cards. Tested as
a module, no idea if it works when compiled into kernel.
*/
static const char *version =
- "eepro.c: v0.11b 08/12/1998 dupuis@lei.ucl.ac.be\n";
+ "eepro.c: v0.11d 08/12/1998 dupuis@lei.ucl.ac.be\n";
#include <linux/module.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/dma.h>
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
-#include <asm/spinlock.h>
-#endif
#include <linux/errno.h>
#include <linux/netdevice.h>
/* For linux 2.1.xx */
#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+#include <asm/spinlock.h>
#include <linux/init.h>
#include <linux/delay.h>
/* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */
#define SLOW_DOWN inb(0x80)
/* udelay(2) */
+#define compat_init_func(X) __initfunc(X)
+#define compat_init_data __initdata
#else
/* for 2.x */
#define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb), (mode) )
#define test_and_set_bit(a,b) set_bit((a),(b))
#define SLOW_DOWN SLOW_DOWN_IO
+#define compat_init_func(X) X
+#define compat_init_data
#endif
/* First, a few definitions that the brave might change. */
/* A zero-terminated list of I/O addresses to be probed. */
-static unsigned int eepro_portlist[] =
+static unsigned int eepro_portlist[] compat_init_data =
{ 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};
/* note: 0x300 is default, the 595FX supports ALL IO Ports
from 0x000 to 0x3F0, some of which are reserved in PCs */
version of the 82595 chip. */
int stepping;
#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
- spinlock_t lock; /* to prevent interrupt within interrupts */
+ spinlock_t lock; /* Serializing lock */
#endif
};
static int eepro_grab_irq(struct device *dev);
/*
- Details of the i82595.
+ Details of the i82595.
You will need either the datasheet or the user manual to understand what
is going on here. The 82595 is very different from the 82586, 82593.
*/
#define RAM_SIZE 0x8000
#define RCV_HEADER 8
-#define RCV_RAM 0x6000 /* 24KB default for RCV buffer */
+#define RCV_RAM 0x6000 /* 24KB default for RCV buffer */
#define RCV_LOWER_LIMIT 0x00 /* 0x0000 */
/* #define RCV_UPPER_LIMIT ((RCV_RAM - 2) >> 8) */ /* 0x5ffe */
#define RCV_UPPER_LIMIT (((rcv_ram) - 2) >> 8)
struct netdev_entry netcard_drv =
{"eepro", eepro_probe1, EEPRO_IO_EXTENT, eepro_portlist};
#else
-int
-eepro_probe(struct device *dev)
+compat_init_func(int eepro_probe(struct device *dev))
{
int i;
int base_addr = dev ? dev->base_addr : 0;
/* Wakeup: */
#define WakeupPort 0x279
#define WakeupSeq {0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,\
- 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,\
- 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,\
- 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43}
+ 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,\
+ 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,\
+ 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43}
{
unsigned short int WS[32]=WakeupSeq;
outb_p(WS[i],WakeupPort);
if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]);
}
- } else printk("Checkregion Failed!\n");
+ } else printk(KERN_WARNING "Checkregion Failed!\n");
}
#endif
if (base_addr > 0x1ff) /* Check a single specified location. */
return eepro_probe1(dev, base_addr);
+
else if (base_addr != 0) /* Don't probe at all. */
return ENXIO;
for (i = 0; eepro_portlist[i]; i++) {
int ioaddr = eepro_portlist[i];
+
if (check_region(ioaddr, EEPRO_IO_EXTENT))
continue;
if (eepro_probe1(dev, ioaddr) == 0)
{
unsigned short Word;
int i,j;
-
+
for (i=0, j=ee_Checksum; i<ee_SIZE; i++)
j+=read_eeprom(ioaddr,i);
printk("Checksum: %#x\n",j&0xffff);
-
+
Word=read_eeprom(ioaddr, 0);
printk(KERN_DEBUG "Word0:\n");
printk(KERN_DEBUG " Plug 'n Pray: %d\n",GetBit(Word,ee_PnP));
printk(KERN_DEBUG " TPE/AUI: %d\n", GetBit(Word,ee_TPE_AUI));
printk(KERN_DEBUG " Jabber: %d\n", GetBit(Word,ee_Jabber));
printk(KERN_DEBUG " AutoPort: %d\n", GetBit(!Word,ee_Jabber));
- printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));
+ printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));
}
- Word=read_eeprom(ioaddr, 5);
+ Word=read_eeprom(ioaddr, 5);
printk(KERN_DEBUG "Word5:\n");
printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE));
printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn));
if (GetBit(Word,ee_PortAUI)) printk("AUI ");
printk("port(s) \n");
- Word=read_eeprom(ioaddr, 6);
+ Word=read_eeprom(ioaddr, 6);
printk(KERN_DEBUG "Word6:\n");
printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask);
printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID);
- Word=read_eeprom(ioaddr, 7);
+ Word=read_eeprom(ioaddr, 7);
printk(KERN_DEBUG "Word7:\n");
printk(KERN_DEBUG " INT to IRQ:\n");
printk(KERN_DEBUG);
- for (i=0, j=0; i<15; i++)
- if (GetBit(Word,i)) printk(" INT%d -> IRQ %d;",j++,i);
+
+ for (i=0, j=0; i<15; i++)
+ if (GetBit(Word,i)) printk(" INT%d -> IRQ %d;",j++,i);
printk("\n");
}
/* Now, we are going to check for the signature of the
ID_REG (register 2 of bank 0) */
-
- id=inb(ioaddr + ID_REG);
+ id=inb(ioaddr + ID_REG);
- printk(KERN_DEBUG " id: %#x ",id);
- printk(" io: %#x ",ioaddr);
+ printk(KERN_DEBUG " id: %#x ",id);
+ printk(" io: %#x ",ioaddr);
if (((id) & ID_REG_MASK) == ID_REG_SIG) {
if (net_debug>3)
printEEPROMInfo(ioaddr);
- if (read_eeprom(ioaddr,7)== ee_FX_INT2IRQ) { /* int to IRQ Mask */
+ if (read_eeprom(ioaddr,7)== ee_FX_INT2IRQ) { /* int to IRQ Mask */
eepro = 2;
printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,",
dev->name, ioaddr);
dev->name, ioaddr);
}
- /* Fill in the 'dev' fields. */
+ /* Fill in the 'dev' fields. */
dev->base_addr = ioaddr;
for (i=0; i < 6; i++) {
printk(", %dK RCV buffer", (int)(dev->mem_end)/1024);
-// outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
-// id = inb(ioaddr + REG3);
-// if (id & TPE_BIT)
-// dev->if_port = TPE;
-// else dev->if_port = BNC;
-
-
/* ............... */
- if (GetBit( read_eeprom(ioaddr, 5),ee_BNC_TPE))
+ if (GetBit( read_eeprom(ioaddr, 5),ee_BNC_TPE))
dev->if_port = BNC;
else dev->if_port = TPE;
-
-
- /* ............... */
-// if (net_debug>3)
-// printk("id: %x\n", id);
+ /* ............... */
if ((dev->irq < 2) && (eepro!=0)) {
for (j=0; ((j<16) && (i>=0)); j++) {
if ((irqMask & (1<<j))!=0) {
- if (i==0) {
- dev->irq = j;
- break; /* found bit corresponding to irq */
- }
+ if (i==0) {
+ dev->irq = j;
+ break; /* found bit corresponding to irq */
+ }
i--; /* count bits set in irqMask */
- }
- }
- if (dev -> irq<2) {
+ }
+ }
+ if (dev -> irq<2) {
printk(" Duh! illegal interrupt vector stored in EEPROM.\n");
return ENODEV;
} else
else if (dev->irq == 2)
dev->irq = 9;
}
-
+
if (dev->irq > 2) {
printk(", IRQ %d, %s.\n", dev->irq,
ifmap[dev->if_port]);
- /*if (request_irq(dev->irq, &eepro_interrupt, 0, "eepro", dev)) {
- printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
- return -EAGAIN;
- }*/
}
else printk(", %s.\n", ifmap[dev->if_port]);
if (net_debug > 3) {
i = read_eeprom(ioaddr, 5);
if (i & 0x2000) /* bit 13 of EEPROM word 5 */
- printk(KERN_DEBUG "%s: Concurrent Processing is enabled but not used!\n",
+ printk(KERN_DEBUG "%s: Concurrent Processing is enabled but not used!\n",
dev->name);
}
printk(version);
/* Grab the region so we can find another board if autoIRQ fails. */
- request_region(ioaddr, EEPRO_IO_EXTENT, "eepro");
+ request_region(ioaddr, EEPRO_IO_EXTENT, dev->name);
/* Initialize the device structure */
dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL);
return -ENOMEM;
memset(dev->priv, 0, sizeof(struct eepro_local));
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ spin_lock_init(&(((struct eepro_local *)dev->priv)->lock));
+#endif
dev->open = eepro_open;
dev->stop = eepro_close;
dev->hard_start_xmit = eepro_send_packet;
{
int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12 };
int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr;
-
- outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
- /* Set the spinlock before activating IRQ! */
- ((struct eepro_local *)dev->priv)->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
+ outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */
/* Enable the interrupt line. */
temp_reg = inb(ioaddr + REG1);
/* clear all interrupts */
outb(ALL_MASK, ioaddr + STATUS_REG);
+
/* Let EXEC event to interrupt */
outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG);
outb(DIAGNOSE_CMD, ioaddr); /* RESET the 82595 */
- if (*irqp == autoirq_report(2) )//&& /* It's a good IRQ line */
- /* We don't take irqs on detection anymore.
- only when actually turning on the driver (ifconfig) */
- /* //(request_irq(dev->irq = *irqp, &eepro_interrupt, 0, "eepro", dev) == 0)) */
- break;
+ if (*irqp == autoirq_report(2)) /* It's a good IRQ line */
+ break;
/* clear all interrupts */
outb(ALL_MASK, ioaddr + STATUS_REG);
struct eepro_local *lp = (struct eepro_local *)dev->priv;
if (net_debug > 3)
- printk(KERN_DEBUG "eepro: entering eepro_open routine.\n");
+ printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name);
if ((irqMask=read_eeprom(ioaddr,7))== ee_FX_INT2IRQ) /* INT to IRQ Mask */
{
- lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */
- if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n");
+ lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */
+ if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n");
}
-
+
else if ((dev->dev_addr[0] == SA_ADDR0 &&
dev->dev_addr[1] == SA_ADDR1 &&
dev->dev_addr[2] == SA_ADDR2))
return -EAGAIN;
}
- if (request_irq(dev->irq , &eepro_interrupt, 0, "eepro", dev)) {
+ if (request_irq(dev->irq , &eepro_interrupt, 0, dev->name, dev)) {
printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
return -EAGAIN;
}
if (((irq2dev_map[dev->irq] != 0)
|| (irq2dev_map[dev->irq] = dev) == 0) &&
(irq2dev_map[dev->irq]!=dev)) {
- /* printk("%s: IRQ map wrong\n", dev->name); */
- return -EAGAIN;
+ /* printk("%s: IRQ map wrong\n", dev->name); */
+ return -EAGAIN;
}
#endif
else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
- temp_reg = inb(ioaddr + INT_NO_REG);
- if (lp->eepro == 2)
- outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG);
- else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
+ temp_reg = inb(ioaddr + INT_NO_REG);
+ if (lp->eepro == 2)
+ outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG);
+ else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
+
+ if (net_debug > 3)
+ printk(KERN_DEBUG "eepro_open: content of INT Reg is %x\n", temp_reg);
- if (net_debug > 3)
- printk(KERN_DEBUG "eepro_open: content of INT Reg is %x\n", temp_reg);
-
-
/* Initialize the RCV and XMT upper and lower limits */
outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG);
/* Let RX and TX events to interrupt */
outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+
/* clear all interrupts */
outb(ALL_MASK, ioaddr + STATUS_REG);
/* Check for the i82595TX and i82595FX */
old8 = inb(ioaddr + 8);
outb(~old8, ioaddr + 8);
+
if ((temp_reg = inb(ioaddr + 8)) == old8) {
if (net_debug > 3)
printk(KERN_DEBUG "i82595 detected!\n");
}
}
else if (net_debug > 3) {
- printk(KERN_DEBUG "temp_reg: %#x ~old9: %#x\n",temp_reg,((~old9)&0xff));
+ printk(KERN_DEBUG "temp_reg: %#x ~old9: %#x\n",temp_reg,((~old9)&0xff));
printk(KERN_DEBUG "i82595TX detected!\n");
}
}
outb(SEL_RESET_CMD, ioaddr);
+
/* We are supposed to wait for 2 us after a SEL_RESET */
SLOW_DOWN;
SLOW_DOWN;
lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */
- lp->tx_last = 0;
+ lp->tx_last = 0;
dev->tbusy = 0;
dev->interrupt = 0;
dev->start = 1;
if (net_debug > 3)
- printk(KERN_DEBUG "eepro: exiting eepro_open routine.\n");
+ printk(KERN_DEBUG "%s: exiting eepro_open routine.\n", dev->name);
outb(RCV_ENABLE_CMD, ioaddr);
int ioaddr = dev->base_addr;
int rcv_ram = dev->mem_end;
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ unsigned long flags;
+#endif
+
if (net_debug > 5)
- printk(KERN_DEBUG "eepro: entering eepro_send_packet routine.\n");
+ printk(KERN_DEBUG "%s: entering eepro_send_packet routine.\n", dev->name);
if (dev->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 < 40)
- return 1;
-
- /* if (net_debug > 1) */
- printk("%s: transmit timed out, %s?\n", dev->name,
- "network cable problem");
- /* This is not a duplicate. One message for the console, one for the
- the log file */
- printk(KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
- "network cable problem");
- lp->stats.tx_errors++;
-
- /* Try to restart the adaptor. */
- outb(SEL_RESET_CMD, ioaddr);
- /* We are supposed to wait for 2 us after a SEL_RESET */
- SLOW_DOWN;
- SLOW_DOWN;
-
- /* Do I also need to flush the transmit buffers here? YES? */
- lp->tx_start = lp->tx_end = rcv_ram;
- lp->tx_last = 0;
+ /* 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 < 40)
+ return 1;
+
+ /* if (net_debug > 1) */
+ printk(KERN_ERR "%s: transmit timed out, %s?\n", dev->name,
+ "network cable problem");
+ /* This is not a duplicate. One message for the console,
+ one for the the log file */
+ printk(KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
+ "network cable problem");
+ lp->stats.tx_errors++;
+
+ /* Try to restart the adaptor. */
+ outb(SEL_RESET_CMD, ioaddr);
+ /* We are supposed to wait for 2 us after a SEL_RESET */
+ SLOW_DOWN;
+ SLOW_DOWN;
+
+ /* Do I also need to flush the transmit buffers here? YES? */
+ lp->tx_start = lp->tx_end = rcv_ram;
+ lp->tx_last = 0;
- dev->tbusy=0;
- dev->trans_start = jiffies;
-
- outb(RCV_ENABLE_CMD, ioaddr);
+ dev->tbusy=0;
+ dev->trans_start = jiffies;
+
+ outb(RCV_ENABLE_CMD, ioaddr);
}
/* 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) {
- // dev_tint(dev);
- // return 0;
- // FIXME : what's this code for ?
- }
+ /* if (skb == NULL) {
+ dev_tint(dev);
+ return 0;
+ }*/
+ /* according to A. Cox, this is obsolete since 1.0 */
#endif
- /* Block a timer-based transmit from overlapping. */
- if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
- printk("%s: Transmitter access conflict.\n", dev->name);
- else {
- short length; unsigned char *buf;
#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
- unsigned long flags;
-
- /* Spin on the lock, until we're clear of an IRQ */
- spin_lock_irqsave(&lp->lock, flags);
+ spin_lock_irqsave(&lp->lock, flags);
#endif
- length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
- buf = skb->data;
+
+ /* Block a timer-based transmit from overlapping. */
+ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+ printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
- lp->stats.tx_bytes+=skb->len;
+ spin_unlock_irqrestore(&lp->lock, flags);
#endif
- hardware_send_packet(dev, buf, length);
-
- dev->trans_start = jiffies;
+ } else {
+ short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+ unsigned char *buf = skb->data;
#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
- spin_unlock_irqrestore(&lp->lock, flags);
-#endif
+ lp->stats.tx_bytes+=skb->len;
+#endif
+
+ hardware_send_packet(dev, buf, length);
+ dev->trans_start = jiffies;
+
}
compat_dev_kfree_skb (skb, FREE_WRITE);
/* lp->stats.tx_aborted_errors++; */
if (net_debug > 5)
- printk(KERN_DEBUG "eepro: exiting eepro_send_packet routine.\n");
+ printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name);
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ spin_unlock_irqrestore(&lp->lock, flags);
+#endif
return 0;
}
+
/* The typical workload of the driver:
Handle the network interface interrupts. */
+
static void
eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct device *dev = (struct device *)dev_id;
/* (struct device *)(irq2dev_map[irq]);*/
-#ifdef __SMP__
struct eepro_local *lp = (struct eepro_local *)dev->priv;
-#endif
int ioaddr, status, boguscount = 20;
- if (test_and_set_bit(0, (void*)&dev->interrupt))
- {
- printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
- dev->name);
- dev->interrupt = 0; /* Avoid halting machine. */
- return;
- }
-
- if (net_debug > 5)
- printk(KERN_DEBUG "eepro: entering eepro_interrupt routine.\n");
-
if (dev == NULL) {
- printk ("eepro_interrupt(): irq %d for unknown device.\n", irq);
+ printk (KERN_ERR "eepro_interrupt(): irq %d for unknown device.\\n", irq);
+ return;
+ }
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ spin_lock(&lp->lock);
+#endif
+
+ if (dev->interrupt) {
+ printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
+
+#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
+ spin_unlock(&lp->lock);
+ /* FIXME : with the lock, could this ever happen ? */
+#endif
+
return;
}
- /* dev->interrupt = 1; */
+ dev->interrupt = 1;
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
- spin_lock(&lp->lock);
-#endif
- ioaddr = dev->base_addr;
+ if (net_debug > 5)
+ printk(KERN_DEBUG "%s: entering eepro_interrupt routine.\n", dev->name);
+
+ ioaddr = dev->base_addr;
- do {
- status = inb(ioaddr + STATUS_REG);
+ do {
+ status = inb(ioaddr + STATUS_REG);
- if (status & RX_INT) {
- if (net_debug > 4)
- printk(KERN_DEBUG "eepro: packet received interrupt.\n");
-
- /* Acknowledge the RX_INT */
- outb(RX_INT, ioaddr + STATUS_REG);
- /* Get the received packets */
- eepro_rx(dev);
- }
-
- else if (status & TX_INT) {
- if (net_debug > 4)
- printk(KERN_DEBUG "eepro: packet transmit interrupt.\n");
-
- /* Acknowledge the TX_INT */
- outb(TX_INT, ioaddr + STATUS_REG);
-
- /* Process the status of transmitted packets */
- eepro_transmit_interrupt(dev);
- }
+ if (status & RX_INT) {
+ if (net_debug > 4)
+ printk(KERN_DEBUG "%s: packet received interrupt.\n", dev->name);
+
+ /* Acknowledge the RX_INT */
+ outb(RX_INT, ioaddr + STATUS_REG);
+ /* Get the received packets */
+ eepro_rx(dev);
+ }
+
+ else if (status & TX_INT) {
+ if (net_debug > 4)
+ printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name);
+
+ /* Acknowledge the TX_INT */
+ outb(TX_INT, ioaddr + STATUS_REG);
+
+ /* Process the status of transmitted packets */
+ eepro_transmit_interrupt(dev);
+ }
} while ((boguscount-- > 0) && (status & 0x06));
dev->interrupt = 0;
if (net_debug > 5)
- printk(KERN_DEBUG "eepro: exiting eepro_interrupt routine.\n");
+ printk(KERN_DEBUG "%s: exiting eepro_interrupt routine.\n", dev->name);
#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
spin_unlock(&lp->lock);
/* Flush the Tx and disable Rx. */
outb(STOP_RCV_CMD, ioaddr);
lp->tx_start = lp->tx_end = rcv_ram ;
- lp->tx_last = 0;
+ lp->tx_last = 0;
/* Mask all the interrupts. */
outb(ALL_MASK, ioaddr + INT_MASK_REG);
outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
printk("%s: promiscuous mode enabled.\n", dev->name);
- }
+ }
+
else if (dev->mc_count==0 )
{
outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
outb(BANK0_SELECT, ioaddr); /* Return to BANK 0 now */
}
+
else
{
unsigned short status, *eaddrs;
outw(0, ioaddr + IO_PORT);
outw(0, ioaddr + IO_PORT);
outw(6*(dev->mc_count + 1), ioaddr + IO_PORT);
+
for (i = 0; i < dev->mc_count; i++)
{
eaddrs=(unsigned short *)dmi->dmi_addr;
outw(*eaddrs++, ioaddr + IO_PORT);
outw(*eaddrs++, ioaddr + IO_PORT);
}
+
eaddrs = (unsigned short *) dev->dev_addr;
outw(eaddrs[0], ioaddr + IO_PORT);
outw(eaddrs[1], ioaddr + IO_PORT);
/* Update the transmit queue */
i = lp->tx_end + XMT_HEADER + 6*(dev->mc_count + 1);
+
if (lp->tx_start != lp->tx_end)
- {
+ {
/* update the next address and the chain bit in the
last packet */
outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
{
i = inb(ioaddr);
outb(0x08, ioaddr + STATUS_REG);
+
if (i & 0x20) { /* command ABORTed */
printk("%s: multicast setup failed.\n",
dev->name);
break;
} else if ((i & 0x0f) == 0x03) { /* MC-Done */
- printk("%s: set Rx mode to %d address%s.\n",
- dev->name, dev->mc_count,
- dev->mc_count > 1 ? "es":"");
+ printk("%s: set Rx mode to %d address%s.\n",
+ dev->name, dev->mc_count,
+ dev->mc_count > 1 ? "es":"");
break;
}
}
/* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read */
/* The delay between EEPROM clock transitions. */
-#define eeprom_delay() { int _i = 40; while (--_i > 0) { SLOW_DOWN; }}
+#define eeprom_delay() { udelay(40); }
#define EE_READ_CMD (6 << 6)
int
unsigned status, tx_available, last, end, boguscount = 100;
if (net_debug > 5)
- printk(KERN_DEBUG "eepro: entering hardware_send_packet routine.\n");
+ printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name);
while (boguscount-- > 0) {
/* Disable RX and TX interrupts. Necessary to avoid
- corruption of the HOST_ADDRESS_REG by interrupt
- service routines. */
+ corruption of the HOST_ADDRESS_REG by interrupt
+ service routines. */
outb(ALL_MASK, ioaddr + INT_MASK_REG);
- if (dev->interrupt == 1) {
+ if (dev->interrupt == 1) {
/* Enable RX and TX interrupts */
outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
continue;
end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
if (end >= RAM_SIZE) { /* the transmit buffer is wrapped around */
+
if ((RAM_SIZE - last) <= XMT_HEADER) {
- /* Arrrr!!!, must keep the xmt header together,
- several days were lost to chase this one down. */
+ /* Arrrr!!!, must keep the xmt header together,
+ several days were lost to chase this one down. */
+
last = rcv_ram;
end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
- }
+ }
+
else end = rcv_ram + (end - RAM_SIZE);
}
lp->tx_start = last; /* I don't like to change tx_start here */
}
else {
- /* update the next address and the chain bit in the
- last packet */
- if (lp->tx_end != last) {
- outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
- outw(last, ioaddr + IO_PORT);
- }
- outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
- status = inw(ioaddr + IO_PORT);
- outw(status | CHAIN_BIT, ioaddr + IO_PORT);
-
- /* Continue the transmit command */
- outb(RESUME_XMT_CMD, ioaddr);
+ /* update the next address and the chain bit in the
+ last packet */
+
+ if (lp->tx_end != last) {
+ outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
+ outw(last, ioaddr + IO_PORT);
+ }
+
+ outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
+ status = inw(ioaddr + IO_PORT);
+ outw(status | CHAIN_BIT, ioaddr + IO_PORT);
+
+ /* Continue the transmit command */
+ outb(RESUME_XMT_CMD, ioaddr);
}
lp->tx_last = last;
}
/* Enable RX and TX interrupts */
- outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
+ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG);
if (net_debug > 5)
- printk(KERN_DEBUG "eepro: exiting hardware_send_packet routine.\n");
+ printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
return;
}
dev->tbusy = 1;
if (net_debug > 5)
- printk(KERN_DEBUG "eepro: exiting hardware_send_packet routine.\n");
+ printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
}
static void
unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size;
if (net_debug > 5)
- printk(KERN_DEBUG "eepro: entering eepro_rx routine.\n");
+ printk(KERN_DEBUG "%s: entering eepro_rx routine.\n", dev->name);
/* Set the read pointer to the start of the RCV */
outw(rcv_car, ioaddr + HOST_ADDRESS_REG);
+
rcv_event = inw(ioaddr + IO_PORT);
while (rcv_event == RCV_DONE) {
- rcv_status = inw(ioaddr + IO_PORT);
- rcv_next_frame = inw(ioaddr + IO_PORT);
- rcv_size = inw(ioaddr + IO_PORT);
+
+ rcv_status = inw(ioaddr + IO_PORT);
+ rcv_next_frame = inw(ioaddr + IO_PORT);
+ rcv_size = inw(ioaddr + IO_PORT);
- if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) {
- /* Malloc up new buffer. */
- struct sk_buff *skb;
+ if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) {
+
+ /* Malloc up new buffer. */
+ struct sk_buff *skb;
#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x20155
- lp->stats.rx_bytes+=rcv_size;
-#endif
- rcv_size &= 0x3fff;
- skb = dev_alloc_skb(rcv_size+5);
- if (skb == NULL) {
- printk("%s: Memory squeeze, dropping packet.\n", dev->name);
- lp->stats.rx_dropped++;
- break;
- }
- skb->dev = dev;
- skb_reserve(skb,2);
-
- if (lp->version == LAN595)
- insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1);
- else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
- unsigned short temp = inb(ioaddr + INT_MASK_REG);
- outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
- insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size),
- (rcv_size + 3) >> 2);
- outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
- }
+ lp->stats.rx_bytes+=rcv_size;
+#endif
+ rcv_size &= 0x3fff;
+ skb = dev_alloc_skb(rcv_size+5);
+ if (skb == NULL) {
+ printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
+ lp->stats.rx_dropped++;
+ break;
+ }
+ skb->dev = dev;
+ skb_reserve(skb,2);
+
+ if (lp->version == LAN595)
+ insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1);
+ else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
+ unsigned short temp = inb(ioaddr + INT_MASK_REG);
+ outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
+ insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size),
+ (rcv_size + 3) >> 2);
+ outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
+ }
- skb->protocol = eth_type_trans(skb,dev);
- netif_rx(skb);
- lp->stats.rx_packets++;
- }
- else { /* Not sure will ever reach here,
- I set the 595 to discard bad received frames */
- lp->stats.rx_errors++;
- if (rcv_status & 0x0100)
- lp->stats.rx_over_errors++;
- else if (rcv_status & 0x0400)
- lp->stats.rx_frame_errors++;
- else if (rcv_status & 0x0800)
- lp->stats.rx_crc_errors++;
- printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
- dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
- }
- if (rcv_status & 0x1000)
- lp->stats.rx_length_errors++;
- if (--boguscount == 0)
- break;
-
- rcv_car = lp->rx_start + RCV_HEADER + rcv_size;
- lp->rx_start = rcv_next_frame;
- outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);
- rcv_event = inw(ioaddr + IO_PORT);
-
+ skb->protocol = eth_type_trans(skb,dev);
+ netif_rx(skb);
+ lp->stats.rx_packets++;
+ }
+
+ else { /* Not sure will ever reach here,
+ I set the 595 to discard bad received frames */
+ lp->stats.rx_errors++;
+
+ if (rcv_status & 0x0100)
+ lp->stats.rx_over_errors++;
+
+ else if (rcv_status & 0x0400)
+ lp->stats.rx_frame_errors++;
+
+ else if (rcv_status & 0x0800)
+ lp->stats.rx_crc_errors++;
+
+ printk("%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
+ dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
+ }
+
+ if (rcv_status & 0x1000)
+ lp->stats.rx_length_errors++;
+
+ if (--boguscount == 0)
+ break;
+
+ rcv_car = lp->rx_start + RCV_HEADER + rcv_size;
+ lp->rx_start = rcv_next_frame;
+ outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);
+ rcv_event = inw(ioaddr + IO_PORT);
+
}
if (rcv_car == 0)
- rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff;
+ rcv_car = (RCV_UPPER_LIMIT << 8) | 0xff;
+
outw(rcv_car - 1, ioaddr + RCV_STOP);
if (net_debug > 5)
- printk(KERN_DEBUG "eepro: exiting eepro_rx routine.\n");
+ printk(KERN_DEBUG "%s: exiting eepro_rx routine.\n", dev->name);
}
static void
/*
if (dev->tbusy == 0) {
- printk("%s: transmit_interrupt called with tbusy = 0 ??\n",
- dev->name);
- printk(KERN_DEBUG "%s: transmit_interrupt called with tbusy = 0 ??\n",
- dev->name);
+ printk("%s: transmit_interrupt called with tbusy = 0 ??\n",
+ dev->name);
+ printk(KERN_DEBUG "%s: transmit_interrupt called with tbusy = 0 ??\n",
+ dev->name);
}
*/
+
while (lp->tx_start != lp->tx_end) {
- outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
- xmt_status = inw(ioaddr+IO_PORT);
- if ((xmt_status & TX_DONE_BIT) == 0) break;
-
- xmt_status = inw(ioaddr+IO_PORT);
- lp->tx_start = inw(ioaddr+IO_PORT);
-
- dev->tbusy = 0;
- mark_bh(NET_BH);
-
- if (xmt_status & 0x2000)
- lp->stats.tx_packets++;
- else {
- lp->stats.tx_errors++;
- if (xmt_status & 0x0400)
- lp->stats.tx_carrier_errors++;
- printk("%s: XMT status = %#x\n",
- dev->name, xmt_status);
- printk(KERN_DEBUG "%s: XMT status = %#x\n",
- dev->name, xmt_status);
- }
- if (xmt_status & 0x000f) {
- lp->stats.collisions += (xmt_status & 0x000f);
- }
- if ((xmt_status & 0x0040) == 0x0) {
- lp->stats.tx_heartbeat_errors++;
- }
-
- if (--boguscount == 0)
- break;
+
+ outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
+ xmt_status = inw(ioaddr+IO_PORT);
+
+ if ((xmt_status & TX_DONE_BIT) == 0) break;
+
+ xmt_status = inw(ioaddr+IO_PORT);
+ lp->tx_start = inw(ioaddr+IO_PORT);
+
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+
+ if (xmt_status & 0x2000)
+ lp->stats.tx_packets++;
+ else {
+ lp->stats.tx_errors++;
+ if (xmt_status & 0x0400)
+ lp->stats.tx_carrier_errors++;
+ printk("%s: XMT status = %#x\n",
+ dev->name, xmt_status);
+ printk(KERN_DEBUG "%s: XMT status = %#x\n",
+ dev->name, xmt_status);
+ }
+
+ if (xmt_status & 0x000f) {
+ lp->stats.collisions += (xmt_status & 0x000f);
+ }
+
+ if ((xmt_status & 0x0040) == 0x0) {
+ lp->stats.tx_heartbeat_errors++;
+ }
+
+ if (--boguscount == 0)
+ break;
}
}
#ifdef MODULE
+
#define MAX_EEPRO 8
static char devicename[MAX_EEPRO][9];
static struct device dev_eepro[MAX_EEPRO];
MODULE_PARM(mem, "i");
#endif
-int init_module(void)
+int
+init_module(void)
{
if (io[0] == 0)
- printk("eepro: You should not use auto-probing with insmod!\n");
+ printk("eepro_init_module: You should not use auto-probing with insmod!\n");
+
while (n_eepro < MAX_EEPRO && io[n_eepro] >= 0) {
struct device *d = &dev_eepro[n_eepro];
d->name = devicename[n_eepro]; /* inserted by drivers/net/net_init.c */
for (i=0; i<n_eepro; i++) {
struct device *d = &dev_eepro[i];
unregister_netdev(d);
+
kfree_s(d->priv,sizeof(struct eepro_local));
d->priv=NULL;
printk(KERN_DEBUG "%s: eexp_xmit()\n", dev->name);
#endif
- outb(SIRQ_dis|irqrmap[dev->irq],dev->base_addr+SET_IRQ);
+ disable_irq(dev->irq);
/* If dev->tbusy is set, all our tx buffers are full but the kernel
* is calling us anyway. Check that nothing bad is happening.
eexp_hw_tx_pio(dev,data,length);
}
dev_kfree_skb(buf);
- outb(SIRQ_en|irqrmap[dev->irq],dev->base_addr+SET_IRQ);
+ enable_irq(dev->irq);
return 0;
}
if( (jiffies - starttime) > TX_TIMEOUT) {
if(eth16i_debug > 1)
- printk(KERN_DEBUG "Timeout occured waiting transmit packet received\n");
+ printk(KERN_DEBUG "Timeout occurred waiting transmit packet received\n");
starttime = jiffies;
while((inb(ioaddr + RX_STATUS_REG) & 0x80) == 0) {
if( (jiffies - starttime) > TX_TIMEOUT) {
if(eth16i_debug > 1)
- printk(KERN_DEBUG "Timeout occured waiting receive packet\n");
+ printk(KERN_DEBUG "Timeout occurred waiting receive packet\n");
return -1;
}
}
/* They return how much memory the fragments need. */
static int hp100_init_rxpdl( struct device *dev, register hp100_ring_t *ringptr, register u32 *pdlptr )
{
- /* pdlptr is starting adress for this pdl */
+ /* pdlptr is starting address for this pdl */
if( 0!=( ((unsigned)pdlptr) & 0xf) )
printk("hp100: %s: Init rxpdl: Unaligned pdlptr 0x%x.\n",dev->name,(unsigned)pdlptr);
- Added code that unregisters irq and proc-info
- Version# bump
+ Mon Nov 16 15:28:23 CET 1998 (Wim Dumon)
+ - pass 'dev' as last parameter of request_irq in stead of 'NULL'
+
* WARNING
-------
This is alpha-test software. It is not guaranteed to work. As a
If it doesn't work, be sure to send me a mail with the problems !
*/
-static const char *version =
-"ne2.c:v0.90 Oct 14 1998 David Weinehall <tao@acc.umu.se>\n";
+static const char *version = "ne2.c:v0.91 Nov 16 1998 Wim Dumon <wimpie@kotnet.org>\n";
#include <linux/module.h>
#include <linux/version.h>
share and the board will usually be enabled. */
{
int irqval = request_irq(dev->irq, ei_interrupt,
- 0, name, NULL);
+ 0, name, dev);
if (irqval) {
printk (" unable to get IRQ %d (irqval=%d).\n",
dev->irq, +irqval);
/* Allocate dev->priv and fill in 8390 specific dev fields. */
if (ethdev_init(dev)) {
printk (" unable to get memory for dev->priv.\n");
- free_irq(dev->irq, NULL);
+ free_irq(dev->irq, dev);
return -ENOMEM;
}
/*
** Disable and Enable Adapter interrupts. Adapter interrupts are enabled at
** Init time but can be disabled and re-enabled through these two function calls.
- ** Packets will still be put into any posted recieved buffers and packets will
+ ** Packets will still be put into any posted received buffers and packets will
** be sent through RCSendPacket() functions. Disabling Adapter interrupts
** will prevent hardware interrupt to host even though the outbound msg
** queue is not emtpy.
}
/*============================================================================
- * Map shared memory window into SDLA adress space.
+ * Map shared memory window into SDLA address space.
*/
EXPORT_SYMBOL(sdla_mapmem);
if(!sktr_chk_ssb(tp, irq_type))
{
- printk(KERN_INFO "%s: DATA LATE occured\n", dev->name);
+ printk(KERN_INFO "%s: DATA LATE occurred\n", dev->name);
break;
}
c |= ACL_SPEED16; /* Set 16Mbps */
}
- /* In case a comand is pending - forget it */
+ /* In case a command is pending - forget it */
tp->ScbInUse = 0;
c &= ~ACL_ARESET; /* Clear adapter reset bit */
} while(retry_cnt > 0);
Status = inw(ioaddr + SIFSTS);
- Status &= STS_ERROR_MASK; /* Hardware error occured! */
+ Status &= STS_ERROR_MASK; /* Hardware error occurred! */
printk(KERN_INFO "%s: Bring Up Diagnostics Error (%04X) occurred\n",
dev->name, Status);
{
if((Status & STS_ERROR) != 0)
{
- /* Initialization error occured */
+ /* Initialization error occurred */
Status = inw(ioaddr + SIFSTS);
Status &= STS_ERROR_MASK;
/* ShowInitialisationErrorCode(Status); */
/*
* The firmware this driver downloads into the tokenring card is a
- * seperate program and is not GPL'd source code, even though the Linux
+ * separate program and is not GPL'd source code, even though the Linux
* side driver and the routine that loads this data into the card are.
*
* This firmware is licensed to you strictly for use in conjunction
lp->tda[entry].tx_frag_ptr_h = laddr >> 16;
lp->tda[entry].tx_frag_size = length;
- /* if there are already packets queued, allow sending serveral packets at once */
+ /* if there are already packets queued, allow sending several packets at once */
if (lp->dirty_tx != lp->cur_tx)
lp->tda[(lp->cur_tx-1) % SONIC_TDS_MASK].link &= ~SONIC_END_OF_LINKS;
*
* Returns:
* No error = 0, else, the stage at which the error
- * occured.
+ * occurred.
* Parms:
* io_base The IO port base address for the
* TLAN device with the EEPROM to
* Receive handler. This is much like the async one but not quite the
* same or as complex
*
- * Note: Its intended that this handler can easily be seperated from
+ * Note: Its intended that this handler can easily be separated from
* the main code to run realtime. That'll be needed for some machines
* (eg to ever clock 64kbits on a sparc ;)).
*
char *p;
/* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */
- for(p = (char *)0xf0000; p < (char *)0x100000; p++)
+ for(p = phys_to_virt(0xf0000); p < phys_to_virt(0x100000); p++)
if (*p == 'N' && strncmp(p, "NETIDBLK", 8) == 0)
break;
- if (p >= (char *)0x100000) {
+ if (p >= pyhs_to_virt(0x100000)) {
if (znet_debug > 1)
printk(KERN_INFO "No Z-Note ethernet adaptor found.\n");
return ENODEV;
but VIA don't answer queries. If you happen to have good contacts at VIA
ask them for me please -- Alan
- This appears to be BIOS not version dependant. So presumably there is a
+ This appears to be BIOS not version dependent. So presumably there is a
chipset level fix */
*
* 0 - successful reception
* non-0 - error value from chip's DER (D-Channel Error Register):
- * 1 - recieved packet abort
+ * 1 - received packet abort
* 2 - framing error; non-integer number of bytes received
* 8 - FCS error; CRC sequence indicated corrupted data
* 16 - overflow error; packet exceeded size of buffer
#define DBRI_RD_M (1<<14) /* Marker interrupt */
#define DBRI_RD_BCNT(v) v /* Buffer size */
#define DBRI_RD_CRC (1<<7) /* 0: CRC is correct */
-#define DBRI_RD_BBC (1<<6) /* 1: Bad Byte recieved */
+#define DBRI_RD_BBC (1<<6) /* 1: Bad Byte received */
#define DBRI_RD_ABT (1<<5) /* Abort: frame aborted */
#define DBRI_RD_OVRN (1<<3) /* Overrun: data lost */
#define DBRI_RD_STATUS(v) ((v)&0xff) /* Receive status */
switch(mode) {
case VFC_I2C_READ:
dev->regs->i2c_reg=raddr=SHIFT((unsigned int)addr | 0x1);
- VFC_I2C_DEBUG_PRINTK(("vfc%d: recieving from i2c addr 0x%x\n",
+ VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n",
dev->instance,addr | 0x1));
break;
case VFC_I2C_WRITE:
if(!count) last=1;
if((ret=vfc_i2c_recv_byte(dev,buf,last))) {
printk(KERN_ERR "vfc%d: "
- "VFC error while recieving byte\n",
+ "VFC error while receiving byte\n",
dev->instance);
dev->regs->i2c_s1=SEND_I2C_STOP;
ret=-EINVAL;
10.6 SCSI BUS checking boot option
11. Some constants and flags of the ncr53c8xx.h header file
12. Installation
-13. Architecture dependant features
+13. Architecture dependent features
14. Known problems
14.1 Tagged commands with Iomega Jaz device
14.2 Device names change when another controller is added
ftp://ftp.tux.org/pub/people/gerard-roudier/README
-13. Architecture dependant features.
+13. Architecture dependent features.
<Not yet written>
* Sequencer RAM Data (p. 3-34)
* Single byte window into the Scratch Ram area starting at the address
* specified by SEQADDR0 and SEQADDR1. To write a full word, simply write
- * four bytes in sucessesion. The SEQADDRs will increment after the most
+ * four bytes in succession. The SEQADDRs will increment after the most
* significant byte is written
*/
register SEQRAM {
-#include <linux/config.h>
-
void swap_statistics(u8 *p)
{
u32 y;
-#include <linux/config.h>
-
/*
* eata_set_info
* buffer : pointer to the data that has been written to the hostfile
/* ------ END OF USER CONFIGURABLE PARAMETERS ----- */
#ifdef IMM_CODE
+#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/kernel.h>
/* ------ END OF USER CONFIGURABLE PARAMETERS ----- */
#ifdef PPA_CODE
+#include <linux/config.h>
#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/kernel.h>
for (dev = 0; dev < shpnt->max_id; ++dev) {
if( shpnt->reverse_ordering)
/* Shift to scanning 15,14,13... or 7,6,5,4, */
- order_dev = shpnt->max_channel-dev-1;
+ order_dev = shpnt->max_id-dev-1;
else
order_dev = dev;
/*
* Note - this means that we just report the status back to the
* top level driver, not that we actually think that it indicates
- * sucess.
+ * success.
*/
return SUCCESS;
/*
* 08/24/1996.
*
* Enhancement for wd7000_detect function has been made, so you don't have
- * to enter BIOS ROM adress in initialisation data (see struct Config).
+ * to enter BIOS ROM address in initialisation data (see struct Config).
* We cannot detect IRQ, DMA and I/O base address for now, so we have to
* enter them as arguments while wd_7000 is detected. If someone has IRQ,
* DMA or I/O base address set to some other value, he can enter them in
int dma1, dma2;
int dual_dma; /* 1, when two DMA channels allocated */
unsigned char MCE_bit;
- unsigned char saved_regs[16];
+ unsigned char saved_regs[32];
int debug_flag;
int audio_flags;
/*
* It's at least CS4231
*/
+
+ devc->chip_name = "CS4231";
+ devc->model = MD_4231;
/*
* It could be an AD1845 or CS4231A as well.
#define SNDCARD_WAVEFRONT 41
#define SNDCARD_OPL3SA2 42
#define SNDCARD_OPL3SA2_MPU 43
+#define SNDCARD_WAVEARTIST 44
#define SNDCARD_AD1816 88
void attach_opl3sa_wss (struct address_info *hw_config);
#endif
#ifdef CONFIG_SOUND_VIDC
{"VIDC", 0, SNDCARD_VIDC, "ARM VIDC 16-bit D/A", attach_vidc, probe_vidc, unload_vidc },
+#endif
+#ifdef CONFIG_SOUND_WAVEARTIST
+ {"WaveArtist", 0, SNDCARD_WAVEARTIST, "NetWinder WaveArtist", attach_waveartist, probe_waveartist, unload_waveartist },
#endif
{NULL, 0, 0, "*?*", NULL, NULL, NULL}
};
#ifdef CONFIG_SOUND_VIDC
{ SNDCARD_VIDC, {0, 0, 0, 0}, SND_DEFAULT_ENABLE },
#endif
+
+#ifdef CONFIG_SOUND_WAVEARTIST
+ { SNDCARD_WAVEARTIST, { CONFIG_WAVEARTIST_BASE, CONFIG_WAVEARTIST_IRQ, CONFIG_WAVEARTIST_DMA, CONFIG_WAVEARTIST_DMA2 }, SND_DEFAULT_ENABLE },
+#endif
{0, {0}, 0}
};
* -- Oliver Neukum <c188@org.chemie.uni-muenchen.de>
* 10.12.98 0.15 Fix drain_dac trying to wait on not yet initialized DMA
* 16.12.98 0.16 Don't wake up app until there are fragsize bytes to read/write
+ * 06.01.99 0.17 remove the silly SA_INTERRUPT flag.
+ * hopefully killed the egcs section type conflict
*
* some important things missing in Ensoniq documentation:
*
/* --------------------------------------------------------------------- */
-static const struct initvol {
+static struct initvol {
int mixch;
int vol;
} initvol[] __initdata = {
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "es1370: version v0.16 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1370: version v0.17 time " __TIME__ " " __DATE__ "\n");
while (index < NR_DEVICE &&
(pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
if (pcidev->base_address[0] == 0 ||
goto err_region;
}
request_region(s->io, ES1370_EXTENT, "es1370");
- if (request_irq(s->irq, es1370_interrupt, SA_INTERRUPT|SA_SHIRQ, "es1370", s)) {
+ if (request_irq(s->irq, es1370_interrupt, SA_SHIRQ, "es1370", s)) {
printk(KERN_ERR "es1370: irq %u in use\n", s->irq);
goto err_irq;
}
* 10.12.98 0.6 Fix drain_dac trying to wait on not yet initialized DMA
* 23.12.98 0.7 Fix a few f_file & FMODE_ bugs
* Don't wake up app until there are fragsize bytes to read/write
+ * 06.01.99 0.8 remove the silly SA_INTERRUPT flag.
+ * hopefully killed the egcs section type conflict
*
*/
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "es1371: version v0.7 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1371: version v0.8 time " __TIME__ " " __DATE__ "\n");
while (index < NR_DEVICE &&
(pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
if (pcidev->base_address[0] == 0 ||
goto err_region;
}
request_region(s->io, ES1371_EXTENT, "es1371");
- if (request_irq(s->irq, es1371_interrupt, SA_INTERRUPT|SA_SHIRQ, "es1371", s)) {
+ if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
goto err_irq;
}
{
unsigned char src;
extern int gus_timer_enabled;
- struct address_info *hw_config=dev_id;
sti();
#ifdef CONFIG_GUSMAX
- if (have_gus_max)
+ if (have_gus_max) {
+ struct address_info *hw_config = dev_id;
adintr(irq, (void *)hw_config->slots[1], NULL);
+ }
#endif
#ifdef CONFIG_GUS16
- if (db16)
+ if (db16) {
+ struct address_info *hw_config = dev_id;
adintr(irq, (void *)hw_config->slots[3], NULL);
+ }
#endif
while (1)
int gus_type = 0x24; /* 2.4 */
int irq = hw_config->irq, dma = hw_config->dma, dma2 = hw_config->dma2;
- int dev;
int sdev;
hw_config->slots[0] = -1; /* No wave */
#define my_malloc_init(memptr) _mem_start = (memptr)
#define my_malloc_memptr() _mem_start
#define my_free(ptr) /* do nothing */
-#define my_realloc(buf,oldsize,size) NULL /* no realloc */
static void *my_malloc(int size)
{
#define my_kmalloc(size) kmalloc(size,GFP_KERNEL)
#define my_kfree(ptr) kfree(ptr)
-static void *my_realloc(void *buf, int oldsize, int size)
-{
- void *ptr;
- if ((ptr = vmalloc(size)) == NULL)
- return NULL;
- memcpy(ptr, buf, ((oldsize < size) ? oldsize : size) );
- vfree(buf);
- return ptr;
-}
-
/* do not allocate buffer at beginning */
#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
for (i = 0xf8d; i <= 0xf93; i++)
DDB(printk("port %03x = %02x\n", i, mad_read(i)));
+ if(!detect_mad16()) {
+
+ /* The C931 has the password reg at F8D */
+ outb((0xE4), 0xF8D);
+ outb((0x80), 0xF8D);
+ DDB(printk("Detect using password = 0xE4 for C931\n"));
- if (!detect_mad16()) {
- board_type = C924;
- c924pnp++;
- DDB(printk("Detect using password = 0xE5 (again), port offset -0x80\n"));
if (!detect_mad16()) {
- c924pnp=0;
- return 0;
- }
+ board_type = C924;
+ c924pnp++;
+ DDB(printk("Detect using password = 0xE5 (again), port offset -0x80\n"));
+ if (!detect_mad16()) {
+ c924pnp=0;
+ return 0;
+ }
- DDB(printk("mad16.c: 82C924 PnP detected\n"));
+ DDB(printk("mad16.c: 82C924 PnP detected\n"));
+ }
}
else
DDB(printk("mad16.c: 82C930 detected\n"));
* A low level driver for Yamaha OPL3-SA2 and SA3 cards.
* SAx cards should work, as they are just variants of the SA3.
*
- * Copyright 1998 Scott Murray <scottm@interlog.com>
+ * Copyright 1998, 1999 Scott Murray <scottm@interlog.com>
*
* Originally based on the CS4232 driver (in cs4232.c) by Hannu Savolainen
* and others. Now incorporates code/ideas from pss.c, also by Hannu
* Scott Murray Changed detection code to be more forgiving,
* added force option as last resort,
* fixed ioctl return values. (Dec 30, 1998)
+ * Scott Murray Simpler detection code should work all the time now
+ * (with thanks to Ben Hutchings for the heuristic),
+ * removed now unnecessary force option. (Jan 5, 1999)
*
*/
#define DEFAULT_MIC 50
#define DEFAULT_TIMBRE 0
+#define CHIPSET_UNKNOWN -1
+
/*
- * NOTE: CHIPSET_UNKNOWN should match the default value of
- * CONFIG_OPL3SA2_CHIPSET in Config.in to make everything
- * work right in all situations.
+ * These are used both as masks against what the card returns,
+ * and as constants.
*/
-#define CHIPSET_UNKNOWN -1
#define CHIPSET_OPL3SA2 1
#define CHIPSET_OPL3SA3 2
#define CHIPSET_OPL3SAX 4
#ifdef CONFIG_OPL3SA2
/* What's my version? */
-#ifdef CONFIG_OPL3SA2_CHIPSET
-/* Set chipset if compiled into the kernel */
-static int chipset = CONFIG_OPL3SA2_CHIPSET;
-#else
static int chipset = CHIPSET_UNKNOWN;
-#endif
/* Oh well, let's just cache the name */
static char chipset_name[16];
int probe_opl3sa2(struct address_info *hw_config)
{
- unsigned char chipsets[8] = { CHIPSET_UNKNOWN, /* 0 */
- CHIPSET_OPL3SA2, /* 1 */
- CHIPSET_OPL3SA3, /* 2 */
- CHIPSET_UNKNOWN, /* 3 */
- CHIPSET_OPL3SAX, /* 4 */
- CHIPSET_OPL3SAX, /* 5 */
- CHIPSET_UNKNOWN, /* 6 */
- CHIPSET_OPL3SA3, /* 7 */ };
unsigned char version = 0;
char tag;
/*
* Determine chipset type (SA2, SA3, or SAx)
- *
- * Have to handle two possible override situations:
- * 1) User compiled driver into the kernel and forced chipset type
- * 2) User built a module, but wants to override the chipset type
*/
- if(chipset == CHIPSET_UNKNOWN)
+
+ /*
+ * Look at chipset version in lower 3 bits of index 0x0A, miscellaneous
+ */
+ opl3sa2_read(hw_config->io_base,
+ OPL3SA2_MISC,
+ (unsigned char*) &version);
+ version &= 0x07;
+
+ /* Match version number to appropiate chipset */
+ if(version & CHIPSET_OPL3SAX)
+ {
+ chipset = CHIPSET_OPL3SAX;
+ tag = 'x';
+ printk(KERN_INFO "Found OPL3-SAx (YMF719)\n");
+ }
+ else
{
- if(hw_config->card_subtype == CHIPSET_UNKNOWN)
+ if(version & CHIPSET_OPL3SA3)
{
- /*
- * Look at chipset version in lower 3 bits of index 0x0A, miscellaneous
- */
- opl3sa2_read(hw_config->io_base,
- OPL3SA2_MISC,
- (unsigned char*) &version);
- version &= 0x07;
-
- /* Match version number to appropiate chipset */
- chipset = chipsets[version];
+ chipset = CHIPSET_OPL3SA3;
+ tag = '3';
+ printk(KERN_INFO "Found OPL3-SA3 (YMF715)\n");
}
else
{
- /* Use user specified chipset */
- switch(hw_config->card_subtype)
+ if(version & CHIPSET_OPL3SA2)
{
- case 2:
- chipset = CHIPSET_OPL3SA2;
- break;
-
- case 3:
- chipset = CHIPSET_OPL3SA3;
- break;
-
- default:
- printk(KERN_ERR "%s: Unknown chipset %d\n",
- __FILE__,
- hw_config->card_subtype);
- chipset = CHIPSET_UNKNOWN;
- break;
- }
- }
- }
- else
- {
- /* Use user compiled in chipset */
- switch(chipset)
- {
- case 2:
chipset = CHIPSET_OPL3SA2;
- break;
-
- case 3:
- chipset = CHIPSET_OPL3SA3;
- break;
-
- default:
- printk(KERN_ERR "%s: Unknown chipset %d\n",
- __FILE__,
- chipset);
- chipset = CHIPSET_UNKNOWN;
- break;
- }
- }
-
- /* Do chipset specific stuff: */
- switch(chipset)
- {
- case CHIPSET_OPL3SA2:
- printk(KERN_INFO "Found OPL3-SA2 (YMF711)\n");
- tag = '2';
- break;
-
- case CHIPSET_OPL3SA3:
- printk(KERN_INFO "Found OPL3-SA3 (YMF715)\n");
- tag = '3';
- break;
-
- case CHIPSET_OPL3SAX:
- printk(KERN_INFO "Found OPL3-SAx (YMF719)\n");
- tag = 'x';
- break;
-
- default:
- printk(KERN_ERR "No Yamaha audio controller found\n");
-
- /* If we've actually checked the version, print it out */
- if(version)
+ tag = '2';
+ printk(KERN_INFO "Found OPL3-SA2 (YMF711)\n");
+ }
+ else
{
+ chipset = CHIPSET_UNKNOWN;
+ tag = '?';
+ printk(KERN_ERR
+ "Unknown Yamaha audio controller version\n");
printk(KERN_INFO
"%s: chipset version = %x\n",
__FILE__,
version);
}
-
- /* Set some sane values */
- chipset = CHIPSET_UNKNOWN;
- tag = '?';
- break;
+ }
}
- if(chipset != CHIPSET_UNKNOWN) {
+ if(chipset != CHIPSET_UNKNOWN)
+ {
/* Generate a pretty name */
sprintf(chipset_name, "OPL3-SA%c", tag);
return 1;
int irq = -1;
int dma = -1;
int dma2 = -1;
-int force = -1;
MODULE_PARM(io, "i");
MODULE_PARM_DESC(io, "Set i/o base of OPL3-SA2 or SA3 card (usually 0x370)");
MODULE_PARM(dma2, "i");
MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)");
-MODULE_PARM(force, "i");
-MODULE_PARM_DESC(force, "Force audio controller chipset (2, 3)");
-
MODULE_DESCRIPTION("Module for OPL3-SA2 and SA3 sound cards (uses AD1848 MSS driver).");
MODULE_AUTHOR("Scott Murray <scottm@interlog.com>");
if(io == -1 || irq == -1 || dma == -1 || dma2 == -1 || mss_io == -1)
{
- printk(KERN_ERR "%s: io, mss_io, irq, dma, and dma2 must be set.\n",
+ printk(KERN_ERR
+ "%s: io, mss_io, irq, dma, and dma2 must be set.\n",
__FILE__);
return -EINVAL;
}
cfg.dma = dma;
cfg.dma2 = dma2;
- /* Does the user want to override the chipset type? */
- if(force != -1)
- cfg.card_subtype = force;
- else
- cfg.card_subtype = CHIPSET_UNKNOWN;
-
/* The MSS config: */
mss_cfg.io_base = mss_io;
mss_cfg.irq = irq;
#define MDL_ES1868MIDI 14 /* MIDI port of ESS1868 */
#define MDL_AEDSP 15 /* Audio Excel DSP 16 */
-#define SUBMDL_ES188X 0x10 /* Subtype ES188X for specific handling */
+#define SUBMDL_ES1788 0x10 /* Subtype ES1788 for specific handling */
#define SUBMDL_ES1868 0x11 /* Subtype ES1868 for specific handling */
#define SUBMDL_ES1869 0x12 /* Subtype ES1869 for specific handling */
#define SUBMDL_ES1878 0x13 /* Subtype ES1878 for specific handling */
+#define SUBMDL_ES188X 0x14 /* Subtype ES1887 for specific handling */
#define SUBMDL_ALS007 42 /* ALS-007 differs from SB16 only in mixer */
/* register assignment */
/*
devc->fullduplex = devc->duplex &&
((mode & OPEN_READ) && (mode & OPEN_WRITE));
sb_dsp_reset(devc);
- ess_mixer_reload (devc, SOUND_MIXER_RECLEV);
+
+ /* At first glance this check isn't enough, some ESS chips might not
+ * have a RECLEV. However if they don't common_mixer_set will refuse
+ * cause devc->iomap has no register mapping for RECLEV
+ */
+ if (devc->model == MDL_ESS) ess_mixer_reload (devc, SOUND_MIXER_RECLEV);
/* The ALS007 seems to require that the DSP be removed from the output */
/* in order for recording to be activated properly. This is done by */
return;
}
+static void ess_change
+ (sb_devc *devc, unsigned int reg, unsigned int mask, unsigned int val)
+{
+ int value;
+
+ value = ess_read(devc, reg);
+ value = (value & ~mask) | (val & mask);
+ ess_write(devc, reg, value);
+}
+
+struct ess_command {int cmd; int data;};
+
+static void ess_exec_commands
+ (sb_devc *devc, struct ess_command *cmdtab[])
+{
+ struct ess_command *cmd;
+
+ cmd = cmdtab [ ((devc->channels != 1) << 1) + (devc->bits != AFMT_U8) ];
+
+ while (cmd->cmd != -1) {
+ ess_write (devc, cmd->cmd, cmd->data);
+ cmd++;
+ }
+}
+
+static struct ess_command ess_i08m[] = /* input 8 bit mono */
+ { {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} };
+static struct ess_command ess_i16m[] = /* input 16 bit mono */
+ { {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} };
+static struct ess_command ess_i08s[] = /* input 8 bit stereo */
+ { {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} };
+static struct ess_command ess_i16s[] = /* input 16 bit stereo */
+ { {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} };
+
+static struct ess_command *ess_inp_cmds[] =
+ { ess_i08m, ess_i16m, ess_i08s, ess_i16s };
+
static int ess_audio_prepare_for_input(int dev, int bsize, int bcount)
{
sb_devc *devc = audio_devs[dev]->devc;
sb_dsp_command(devc, DSP_CMD_SPKOFF);
ess_write(devc, 0xb8, 0x0e); /* Auto init DMA mode */
- ess_write(devc, 0xa8, (ess_read(devc, 0xa8) & ~0x03) | (3 - devc->channels)); /* Mono/stereo */
+ ess_change (devc, 0xa8, 0x03, 3 - devc->channels); /* Mono/stereo */
ess_write(devc, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */
- if (devc->channels == 1)
- {
- if (devc->bits == AFMT_U8)
- {
- /* 8 bit mono */
- ess_write(devc, 0xb7, 0x51);
- ess_write(devc, 0xb7, 0xd0);
- }
- else
- {
- /* 16 bit mono */
- ess_write(devc, 0xb7, 0x71);
- ess_write(devc, 0xb7, 0xf4);
- }
- }
- else
- {
- /* Stereo */
- if (devc->bits == AFMT_U8)
- {
- /* 8 bit stereo */
- ess_write(devc, 0xb7, 0x51);
- ess_write(devc, 0xb7, 0x98);
- }
- else
- {
- /* 16 bit stereo */
- ess_write(devc, 0xb7, 0x71);
- ess_write(devc, 0xb7, 0xbc);
- }
- }
- ess_write(devc, 0xb1, (ess_read(devc, 0xb1) & 0x0f) | 0x50);
- ess_write(devc, 0xb2, (ess_read(devc, 0xb2) & 0x0f) | 0x50);
+ ess_exec_commands (devc, ess_inp_cmds);
+
+ ess_change (devc, 0xb1, 0xf0, 0x50);
+ ess_change (devc, 0xb2, 0xf0, 0x50);
+
devc->trigger_bits = 0;
return 0;
}
+static struct ess_command ess_o08m[] = /* output 8 bit mono */
+ { {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} };
+static struct ess_command ess_o16m[] = /* output 16 bit mono */
+ { {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} };
+static struct ess_command ess_o08s[] = /* output 8 bit stereo */
+ { {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} };
+static struct ess_command ess_o16s[] = /* output 16 bit stereo */
+ { {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} };
+
+
+static struct ess_command *ess_out_cmds[] =
+ { ess_o08m, ess_o16m, ess_o08s, ess_o16s };
+
static int ess_audio_prepare_for_output(int dev, int bsize, int bcount)
{
sb_devc *devc = audio_devs[dev]->devc;
ess_speed(devc);
ess_write(devc, 0xb8, 4); /* Auto init DMA mode */
- ess_write(devc, 0xa8, (ess_read(devc, 0xa8) & ~0x03) | (3 - devc->channels)); /* Mono/stereo */
+ ess_change (devc, 0xa8, 0x03, 3 - devc->channels); /* Mono/stereo */
ess_write(devc, 0xb9, 2); /* Demand mode (4 bytes/request) */
- if (devc->channels == 1)
- {
- if (devc->bits == AFMT_U8)
- { /* 8 bit mono */
- ess_write(devc, 0xb6, 0x80);
- ess_write(devc, 0xb7, 0x51);
- ess_write(devc, 0xb7, 0xd0);
- }
- else
- { /* 16 bit mono */
- ess_write(devc, 0xb6, 0x00);
- ess_write(devc, 0xb7, 0x71);
- ess_write(devc, 0xb7, 0xf4);
- }
- }
- else
- { /* Stereo */
- if (devc->bits == AFMT_U8)
- { /* 8 bit stereo */
- ess_write(devc, 0xb6, 0x80);
- ess_write(devc, 0xb7, 0x51);
- ess_write(devc, 0xb7, 0x98);
- }
- else
- { /* 16 bit stereo */
- ess_write(devc, 0xb6, 0x00);
- ess_write(devc, 0xb7, 0x71);
- ess_write(devc, 0xb7, 0xbc);
- }
- }
+ ess_exec_commands (devc, ess_out_cmds);
+
+ ess_change (devc, 0xb1, 0xf0, 0x50);
+ ess_change (devc, 0xb2, 0xf0, 0x50);
- ess_write(devc, 0xb1, (ess_read(devc, 0xb1) & 0x0f) | 0x50);
- ess_write(devc, 0xb2, (ess_read(devc, 0xb2) & 0x0f) | 0x50);
sb_dsp_command(devc, DSP_CMD_SPKON);
devc->trigger_bits = 0;
ess_write(devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
ess_write(devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
- ess_write(devc, 0xb8, ess_read(devc, 0xb8) | 0x05); /* Go */
+ ess_change (devc, 0xb8, 0x05, 0x05); /* Go */
devc->intr_active = 1;
}
ess_write(devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff));
ess_write(devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff));
-
- ess_write(devc, 0xb8, ess_read(devc, 0xb8) | 0x0f); /* Go */
+
+ ess_change (devc, 0xb8, 0x0f, 0x0f); /* Go */
devc->intr_active = 1;
}
/*
* Daniel J. Rodriksson: Modified sbintr to handle 8 and 16 bit interrupts
* for full duplex support ( only sb16 by now )
- * Rolf Fokkens: Added (BETA?) support for ES188x chips.
+ * Rolf Fokkens: Added (BETA?) support for ES1887 chips.
* (fokkensr@vertis.nl) Which means: You can adjust the recording levels.
*/
#include <linux/config.h>
/*
* This the detection heuristic of ESS technology, though somewhat
* changed to actually make it work.
+ * This results in the following detection steps:
+ * - distinct between ES688 and ES1688+ (as always done in this driver)
+ * if ES688 we're ready
+ * - try to detect ES1868, ES1869 or ES1878 (ess_identify)
+ * if successful we're ready
+ * - try to detect ES1888, ES1887 or ES1788 (aim: detect ES1887)
+ * if successful we're ready
+ * - Dunno. Must be 1688. Will do in general
+ *
* This is the most BETA part of the software: Will the detection
* always work?
*/
chip = "ES688";
};
if (chip == NULL) {
- int type, dummy;
+ int type;
type = ess_identify (devc);
break;
};
};
- if (chip == NULL) {
- if ( !ess_probe (devc, 0x64, (1 << 3))
- && ess_probe (devc, 0x70, 0x7f)) {
- chip = "ES188x";
+ if (chip == NULL && !ess_probe(devc, 0x64, (1 << 3))) {
+ if (ess_probe (devc, 0x70, 0x7f)) {
+ if (ess_probe (devc, 0x64, (1 << 5))) {
+ chip = "ES1887";
+ } else {
+ chip = "ES1888";
+ }
devc->submodel = SUBMDL_ES188X;
- };
+ } else {
+ chip = "ES1788";
+ devc->submodel = SUBMDL_ES1788;
+ }
};
if (chip == NULL) {
chip = "ES1688";
/*
* Mixer access routines
*
- * ES188x modifications: some mixer registers reside in the
+ * ES1887 modifications: some mixer registers reside in the
* range above 0xa0. These must be accessed in another way.
*/
return val;
}
-
+/*
+ * Some PnP chips can be identified by repeatedly reading mixer register 0x40.
+ * This is done by ess_identify
+ */
static unsigned int ess_identify (sb_devc * devc)
{
unsigned int val;
*
* Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
* Rolf Fokkens (Dec 20 1998) : ES188x recording level support on a per
- * input basis
- * (Dec 24 1998) : Recognition of ES188x (?), ES1868, ES1869
- * and ES1878. Could be used for specific
- * handling in the future. All except ES188x
- * and ES688 are handled like ES1688
- * (Dec 27 1998) : RECLEV for all (?) ES1688+ chips, see
- * ess_mixer_reload for more info. ES188x now
- * has the "Dec 20" support + RECLEV
+ * input basis.
+ * (Dec 24 1998) : Recognition of ES1788, ES1887, ES1888,
+ * ES1868, ES1869 and ES1878. Could be used for
+ * specific handling in the future. All except
+ * ES1887 and ES1888 and ES688 are handled like
+ * ES1688.
+ * (Dec 27 1998) : RECLEV for all (?) ES1688+ chips. ES188x now
+ * have the "Dec 20" support + RECLEV
*/
/*
- * About ES188x support:
+ * About the documentation
+ *
+ * I don't know if the chips all are OK, but the documentation is buggy. 'cause
+ * I don't have all the cips myself, there's a lot I cannot verify. I'll try to
+ * keep track of my latest insights about his here. If you have additional info,
+ * please enlighten me (fokkensr@vertis.nl)!
*
- * The standard ES1688 support doesn't take care of the ES188x recording
- * levels very well. Whenever a device is selected (recmask) for recording
- * it's recording level is loud, and it cannot be changed.
+ * I had the impression that ES1688 also has 6 bit master volume control. The
+ * documentation about ES1888 (rev C, october '95) claims that ES1888 has
+ * the following features ES1688 doesn't have:
+ * - 6 bit master volume
+ * - Full Duplex
+ * So ES1688 apparently doesn't have 6 bit master volume control, but the
+ * ES1688 does have RECLEV control. Makes me wonder: does ES688 have it too?
+ * Without RECLEV ES688 won't be much fun I guess.
*
- * The ES188x has separate registers to control the recording levels. The
- * ES188x specific software makes these level the same as their corresponding
- * playback levels, unless recmask says they aren't recorded. In the latter
- * case the recording volumes are 0.
+ * From the ES1888 (rev C, october '95) documentation I got the impression
+ * that registers 0x68 to 0x6e don't exist which means: no recording volume
+ * controls. To my surprise the ES888 documentation (1/14/96) claims that
+ * ES888 does have these record mixer registers, but that ES1888 doesn't have
+ * 0x69 and 0x6b. So the rest should be there.
+ *
+ */
+
+/*
+ * About recognition of ESS chips
+ *
+ * The distinction of ES688, ES1688, ES1788, ES1887 and ES1888 is described in
+ * a (preliminary ??) datasheet on ES1887. It's aim is to identify ES1887, but
+ * during detection the text claims that "this chip may be ..." when a step
+ * fails. This scheme is used to distinct between the above chips.
+ * It appears however that some PnP chips like ES1868 are recognized as ES1788
+ * by the ES1887 detection scheme. These PnP chips can be detected in another
+ * way however: ES1868, ES1869 and ES1878 can be recognized (full proof I think)
+ * by repeatedly reading mixer register 0x40. This is done by ess_identify in
+ * sb_common.c.
+ * This results in the following detection steps:
+ * - distinct between ES688 and ES1688+ (as always done in this driver)
+ * if ES688 we're ready
+ * - try to detect ES1868, ES1869 or ES1878
+ * if successful we're ready
+ * - try to detect ES1888, ES1887 or ES1788
+ * if successful we're ready
+ * - Dunno. Must be 1688. Will do in general
+ *
+ * About RECLEV support:
+ *
+ * The existing ES1688 support didn't take care of the ES1688+ recording
+ * levels very well. Whenever a device was selected (recmask) for recording
+ * it's recording level was loud, and it couldn't be changed. The fact that
+ * internal register 0xb4 could take care of RECLEV, didn't work meaning until
+ * it's value was restored every time the chip was reset; this reset the
+ * value of 0xb4 too. I guess that's what 4front also had (have?) trouble with.
+ *
+ * About ES188x support:
*
+ * The ES188x has separate registers to control the recording levels, for all
+ * inputs. The ES188x specific software makes these levels the same as their
+ * corresponding playback levels, unless recmask says they aren't recorded. In
+ * the latter case the recording volumes are 0.
* Now recording levels of inputs can be controlled, by changing the playback
* levels. Futhermore several devices can be recorded together (which is not
* possible with the ES1688.
+ * Besides the separate recording level control for each input, the common
+ * recordig level can also be controlled by RECLEV as described above.
*/
#include <linux/config.h>
#include "sb.h"
#include "sb_mixer.h"
+#define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
+
+/* Same as SB Pro, unless I find otherwise */
+#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
+
+#define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD | SOUND_MASK_VOLUME)
+
+/* SG NX Pro has treble and bass settings on the mixer. The 'speaker'
+ * channel is the COVOX/DisneySoundSource emulation volume control
+ * on the mixer. It does NOT control speaker volume. Should have own
+ * mask eventually?
+ */
+#define SGNXPRO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
+ SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
+
+#define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD)
+
+#define SB16_OUTFILTER_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD)
+
+#define ES688_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
+#define ES688_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_LINE2|SOUND_MASK_SPEAKER)
+
+#define ES1688_RECORDING_DEVICES ES688_RECORDING_DEVICES
+#define ES1688_MIXER_DEVICES (ES688_MIXER_DEVICES|SOUND_MASK_RECLEV)
+
+#define ES188X_RECORDING_DEVICES (ES1688_RECORDING_DEVICES | SOUND_MASK_LINE2 \
+ |SOUND_MASK_SYNTH)
+#define ES188X_MIXER_DEVICES (ES1688_MIXER_DEVICES)
+
+#define SB16_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD | \
+ SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
+ SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
+ SOUND_MASK_IMIX)
+
+/* These are the only devices that are working at the moment. Others could
+ * be added once they are identified and a method is found to control them.
+ */
+#define ALS007_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
+ SOUND_MASK_PCM | SOUND_MASK_MIC | \
+ SOUND_MASK_CD | \
+ SOUND_MASK_VOLUME)
+
+/*
+ * Mixer registers of ES188x
+ *
+ * These registers specifically take care of recording levels. To make the
+ * mapping from playback devices to recording devices every recording
+ * devices = playback device + ES188X_MIXER_RECDIFF
+ */
+#define ES188X_MIXER_RECBASE (SOUND_MIXER_LINE3 + 1)
+#define ES188X_MIXER_RECDIFF (ES188X_MIXER_RECBASE - SOUND_MIXER_SYNTH)
+
+#define ES188X_MIXER_RECSYNTH (SOUND_MIXER_SYNTH + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECPCM (SOUND_MIXER_PCM + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECSPEAKER (SOUND_MIXER_SPEAKER + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE (SOUND_MIXER_LINE + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECMIC (SOUND_MIXER_MIC + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECCD (SOUND_MIXER_CD + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECIMIX (SOUND_MIXER_IMIX + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECALTPCM (SOUND_MIXER_ALTPCM + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECRECLEV (SOUND_MIXER_RECLEV + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECIGAIN (SOUND_MIXER_IGAIN + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECOGAIN (SOUND_MIXER_OGAIN + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE1 (SOUND_MIXER_LINE1 + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE2 (SOUND_MIXER_LINE2 + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE3 (SOUND_MIXER_LINE3 + ES188X_MIXER_RECDIFF)
+
static mixer_tab sbpro_mix = {
MIX_ENT(SOUND_MIXER_VOLUME, 0x22, 7, 4, 0x22, 3, 4),
MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
/*
* The ES1688 specifics... hopefully correct...
* - 6 bit master volume
+ * I was wrong, ES1888 docs say ES1688 didn't have it.
* - RECLEV control
* These may apply to ES688 too. I have no idea.
*/
static mixer_tab es1688_mix = {
-MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6),
+MIX_ENT(SOUND_MIXER_VOLUME, 0x32, 7, 4, 0x32, 3, 4),
MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0)
};
+static mixer_tab es1688later_mix = {
+MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6),
+MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH, 0x36, 7, 4, 0x36, 3, 4),
+MIX_ENT(SOUND_MIXER_PCM, 0x14, 7, 4, 0x14, 3, 4),
+MIX_ENT(SOUND_MIXER_SPEAKER, 0x3c, 2, 3, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE, 0x3e, 7, 4, 0x3e, 3, 4),
+MIX_ENT(SOUND_MIXER_MIC, 0x1a, 7, 4, 0x1a, 3, 4),
+MIX_ENT(SOUND_MIXER_CD, 0x38, 7, 4, 0x38, 3, 4),
+MIX_ENT(SOUND_MIXER_IMIX, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV, 0xb4, 7, 4, 0xb4, 3, 4),
+MIX_ENT(SOUND_MIXER_IGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE2, 0x3a, 7, 4, 0x3a, 3, 4),
+MIX_ENT(SOUND_MIXER_LINE3, 0x00, 0, 0, 0x00, 0, 0)
+};
+
/*
* The ES188x specifics.
* Note that de master volume unlike ES688 is now controlled by two 6 bit
- * registers. These seem to work OK on 1868 too, but I have no idea if it's
- * compatible to 688 or 1688....
+ * registers. These seem to work OK on 1868 too.
* Also Note that the recording levels (ES188X_MIXER_REC...) have own
* entries as if they were playback devices. They are used internally in the
* driver only!
0x00 /* SOUND_MIXER_LINE3 */
};
-#define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
-
-/* Same as SB Pro, unless I find otherwise */
-#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
-
-#define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
- SOUND_MASK_CD | SOUND_MASK_VOLUME)
-
-/* SG NX Pro has treble and bass settings on the mixer. The 'speaker'
- * channel is the COVOX/DisneySoundSource emulation volume control
- * on the mixer. It does NOT control speaker volume. Should have own
- * mask eventually?
- */
-#define SGNXPRO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
- SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
-
-#define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
- SOUND_MASK_CD)
-
-#define SB16_OUTFILTER_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \
- SOUND_MASK_CD)
-
-#define ES688_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
-#define ES688_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_LINE2|SOUND_MASK_SPEAKER)
-
-#define ES1688_RECORDING_DEVICES ES688_RECORDING_DEVICES
-#define ES1688_MIXER_DEVICES (ES688_MIXER_DEVICES|SOUND_MASK_RECLEV)
-
-#define ES188X_RECORDING_DEVICES (ES1688_RECORDING_DEVICES | SOUND_MASK_LINE2 \
- |SOUND_MASK_SYNTH)
-#define ES188X_MIXER_DEVICES (ES1688_MIXER_DEVICES)
-
-#define SB16_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
- SOUND_MASK_CD | \
- SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
- SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
- SOUND_MASK_IMIX)
-
-/* These are the only devices that are working at the moment. Others could
- * be added once they are identified and a method is found to control them.
- */
-#define ALS007_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
- SOUND_MASK_PCM | SOUND_MASK_MIC | \
- SOUND_MASK_CD | \
- SOUND_MASK_VOLUME)
-
-/*
- * Mixer registers of ES188x
- *
- * These registers specifically take care of recording levels. To make the
- * mapping from playback devices to recording devices every recording
- * devices = playback device + ES188X_MIXER_RECDIFF
- */
-#define ES188X_MIXER_RECBASE (SOUND_MIXER_LINE3 + 1)
-#define ES188X_MIXER_RECDIFF (ES188X_MIXER_RECBASE - SOUND_MIXER_SYNTH)
-
-#define ES188X_MIXER_RECSYNTH (SOUND_MIXER_SYNTH + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECPCM (SOUND_MIXER_PCM + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECSPEAKER (SOUND_MIXER_SPEAKER + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE (SOUND_MIXER_LINE + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECMIC (SOUND_MIXER_MIC + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECCD (SOUND_MIXER_CD + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECIMIX (SOUND_MIXER_IMIX + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECALTPCM (SOUND_MIXER_ALTPCM + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECRECLEV (SOUND_MIXER_RECLEV + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECIGAIN (SOUND_MIXER_IGAIN + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECOGAIN (SOUND_MIXER_OGAIN + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE1 (SOUND_MIXER_LINE1 + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE2 (SOUND_MIXER_LINE2 + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE3 (SOUND_MIXER_LINE3 + ES188X_MIXER_RECDIFF)
-
-
static int sbmixnum = 1;
static void sb_mixer_reset(sb_devc * devc);
= ES688_RECORDING_DEVICES;
devc->iomap = &es688_mix;
} else {
+ /*
+ * es1688 has 4 bits master vol.
+ * later chips have 6 bits (?)
+ */
devc->supported_devices
= ES1688_MIXER_DEVICES;
devc->supported_rec_devices
= ES1688_RECORDING_DEVICES;
- devc->iomap = &es1688_mix;
+ if (devc->submodel < 0x10) {
+ devc->iomap = &es1688_mix;
+ } else {
+ devc->iomap = &es1688later_mix;
+ }
}
}
#ifdef CONFIG_SBDSP
-#define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
-
-/* Same as SB Pro, unless I find otherwise */
-#define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
-
-#define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
- SOUND_MASK_CD | SOUND_MASK_VOLUME)
-
-/* SG NX Pro has treble and bass settings on the mixer. The 'speaker'
- * channel is the COVOX/DisneySoundSource emulation volume control
- * on the mixer. It does NOT control speaker volume. Should have own
- * mask eventually?
- */
-#define SGNXPRO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
- SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
-
-#define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
- SOUND_MASK_CD)
-
-#define SB16_OUTFILTER_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \
- SOUND_MASK_CD)
-
-#define ES688_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
-#define ES688_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_LINE2|SOUND_MASK_SPEAKER)
-
-#define ES1688_RECORDING_DEVICES ES688_RECORDING_DEVICES
-#define ES1688_MIXER_DEVICES (ES688_MIXER_DEVICES|SOUND_MASK_RECLEV)
-
-#define ES188X_RECORDING_DEVICES (ES1688_RECORDING_DEVICES | SOUND_MASK_LINE2 \
- |SOUND_MASK_SYNTH)
-#define ES188X_MIXER_DEVICES (ES1688_MIXER_DEVICES)
-
-#define SB16_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
- SOUND_MASK_CD | \
- SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
- SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
- SOUND_MASK_IMIX)
-
-/* These are the only devices that are working at the moment. Others could
- * be added once they are identified and a method is found to control them.
- */
-#define ALS007_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
- SOUND_MASK_PCM | SOUND_MASK_MIC | \
- SOUND_MASK_CD | \
- SOUND_MASK_VOLUME)
/*
* Mixer registers
*
#define LEFT_CHN 0
#define RIGHT_CHN 1
-/*
- * Mixer registers of ES188x
- *
- * These registers specifically take care of recording levels. To make the
- * mapping from playback devices to recording devices every recording
- * devices = playback device + ES188X_MIXER_RECDIFF
- */
-#define ES188X_MIXER_RECBASE (SOUND_MIXER_LINE3 + 1)
-#define ES188X_MIXER_RECDIFF (ES188X_MIXER_RECBASE - SOUND_MIXER_SYNTH)
-
-#define ES188X_MIXER_RECSYNTH (SOUND_MIXER_SYNTH + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECPCM (SOUND_MIXER_PCM + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECSPEAKER (SOUND_MIXER_SPEAKER + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE (SOUND_MIXER_LINE + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECMIC (SOUND_MIXER_MIC + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECCD (SOUND_MIXER_CD + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECIMIX (SOUND_MIXER_IMIX + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECALTPCM (SOUND_MIXER_ALTPCM + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECRECLEV (SOUND_MIXER_RECLEV + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECIGAIN (SOUND_MIXER_IGAIN + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECOGAIN (SOUND_MIXER_OGAIN + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE1 (SOUND_MIXER_LINE1 + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE2 (SOUND_MIXER_LINE2 + ES188X_MIXER_RECDIFF)
-#define ES188X_MIXER_RECLINE3 (SOUND_MIXER_LINE3 + ES188X_MIXER_RECDIFF)
-
/*
* Mixer registers of ALS007
*/
#define ALS007_SYNTH 7
#endif
+
* 31.08.98 0.7 Fix realplayer problems - dac.count issues
* 10.12.98 0.8 Fix drain_dac trying to wait on not yet initialized DMA
* 16.12.98 0.9 Fix a few f_file & FMODE_ bugs
+ * 06.01.99 0.10 remove the silly SA_INTERRUPT flag.
+ * hopefully killed the egcs section type conflict
*
*/
/* --------------------------------------------------------------------- */
-static const struct initvol {
+static struct initvol {
int mixch;
int vol;
} initvol[] __initdata = {
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "sv: version v0.9 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "sv: version v0.10 time " __TIME__ " " __DATE__ "\n");
#if 0
if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
wrindir(s, SV_CIPCMSR1, ((8000 * 65536 / FULLRATE) >> 8) & 0xff);
wrindir(s, SV_CIADCOUTPUT, 0);
/* request irq */
- if (request_irq(s->irq, sv_interrupt, SA_INTERRUPT|SA_SHIRQ, "S3 SonicVibes", s)) {
+ if (request_irq(s->irq, sv_interrupt, SA_SHIRQ, "S3 SonicVibes", s)) {
printk(KERN_ERR "sv: irq %u in use\n", s->irq);
goto err_irq;
}
return -ENODEV;
}
+extern int mod_firmware_load(const char *, char **);
+EXPORT_SYMBOL(mod_firmware_load);
+
#ifdef MODULE
MODULE_DESCRIPTION("Core sound module");
MODULE_AUTHOR("Alan Cox");
-extern int mod_firmware_load(const char *, char **);
-EXPORT_SYMBOL(mod_firmware_load);
-
-
void cleanup_module(void)
{
/* We have nothing to really do here - we know the lists must be
--- /dev/null
+/*
+ * drivers/sound/waveartist.c
+ *
+ * The low level driver for the RWA010 Rockwell Wave Artist
+ * codec chip used in the Corel Computer NetWinder.
+ *
+ * Cleaned up and integrated into 2.1 by Russell King (rmk@arm.linux.org.uk)
+ */
+
+/*
+ * Copyright (C) by Corel Computer 1998
+ *
+ * RWA010 specs received under NDA from Rockwell
+ *
+ * Copyright (C) by Hannu Savolainen 1993-1997
+ *
+ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ * Version 2 (June 1991). See the "COPYING" file distributed with this software
+ * for more info.
+ */
+
+/* Debugging */
+#define DEBUG_CMD 1
+#define DEBUG_OUT 2
+#define DEBUG_IN 4
+#define DEBUG_INTR 8
+#define DEBUG_MIXER 16
+#define DEBUG_TRIGGER 32
+
+#define debug_flg (0)
+
+#define DEB(x)
+#define DDB(x)
+#define DEB1(x)
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+
+#include <asm/hardware.h>
+
+#include "soundmodule.h"
+#include "sound_config.h"
+#include "waveartist.h"
+
+#define VNC_TIMER_PERIOD (HZ/4) //check slider 4 times/sec
+
+#define MIXER_PRIVATE3_RESET 0x53570000
+#define MIXER_PRIVATE3_READ 0x53570001
+#define MIXER_PRIVATE3_WRITE 0x53570002
+
+#define VNC_INTERNAL_SPKR 0x01 //the sw mute on/off control bit
+#define VNC_INTERNAL_MIC 0x10 //the hw internal/handset mic bit
+
+/* Use RECSRC = speaker to mark the internal microphone
+ *
+ * Some cheating involved here: there is no way to relay
+ * to the system, which microphone in in use
+ * (left = handset, or right = internal)
+ *
+ * So while I do not flag SPEAKER in the Recording Devices
+ * Mask, when on internal
+ *
+ * mike - I set the speaker bit hi. Some mixers can be
+ * confused a bit...
+ */
+
+#define POSSIBLE_RECORDING_DEVICES (SOUND_MASK_LINE |\
+ SOUND_MASK_MIC |\
+ SOUND_MASK_LINE1) //Line1 = analog phone
+
+#define SUPPORTED_MIXER_DEVICES (SOUND_MASK_SYNTH |\
+ SOUND_MASK_PCM |\
+ SOUND_MASK_LINE |\
+ SOUND_MASK_MIC | \
+ SOUND_MASK_LINE1 |\
+ SOUND_MASK_RECLEV |\
+ SOUND_MASK_VOLUME)
+
+static unsigned short levels[SOUND_MIXER_NRDEVICES] = {
+ 0x5555, /* Master Volume */
+ 0x0000, /* Bass */
+ 0x0000, /* Treble */
+ 0x5555, /* Synth (FM) */
+ 0x4b4b, /* PCM */
+ 0x0000, /* PC Speaker */
+ 0x0000, /* Ext Line */
+ 0x0000, /* Mic */
+ 0x0000, /* CD */
+ 0x0000, /* Recording monitor */
+ 0x0000, /* SB PCM (ALT PCM) */
+ 0x0000, /* Recording level */
+ 0x0000, /* Input gain */
+ 0x0000, /* Output gain */
+ 0x0000, /* Line1 (Aux1) */
+ 0x0000, /* Line2 (Aux2) */
+ 0x0000, /* Line3 (Aux3) */
+ 0x0000, /* Digital1 */
+ 0x0000, /* Digital2 */
+ 0x0000, /* Digital3 */
+ 0x0000, /* Phone In */
+ 0x0000, /* Phone Out */
+ 0x0000, /* Video */
+ 0x0000, /* Radio */
+ 0x0000 /* Monitor */
+};
+
+typedef struct {
+ struct address_info hw; /* hardware */
+ char *chip_name;
+
+ int xfer_count;
+ int audio_mode;
+ int open_mode;
+ int audio_flags;
+ int record_dev;
+ int playback_dev;
+ int dev_no;
+
+ /* Mixer parameters */
+ unsigned short *levels;
+ int handset_state;
+ signed int slider_vol; /* hardware slider volume */
+ int recmask; /* currently enabled recording device! */
+ int supported_devices; /* SUPPORTED_MIXER_DEVICES */
+ int rec_devices; /* POSSIBLE_RECORDING_DEVICES */
+ int handset_mute_sw :1;/* 1 - handset controlled in sw */
+ int use_slider :1;/* use slider setting for o/p vol */
+ int mute_state :1;
+} wavnc_info;
+
+typedef struct wavnc_port_info {
+ int open_mode;
+ int speed;
+ int channels;
+ int audio_format;
+} wavnc_port_info;
+
+static int nr_waveartist_devs;
+static wavnc_info adev_info[MAX_AUDIO_DEV];
+static struct timer_list vnc_timer;
+
+
+static inline void
+waveartist_set_ctlr(struct address_info *hw, unsigned char clear, unsigned char set)
+{
+ unsigned int ctlr_port = hw->io_base + CTLR;
+
+ clear = ~clear & inb(ctlr_port);
+
+ outb(clear | set, ctlr_port);
+}
+
+/* Toggle IRQ acknowledge line
+ */
+static inline void
+waveartist_iack(wavnc_info *devc)
+{
+ unsigned int ctlr_port = devc->hw.io_base + CTLR;
+ int old_ctlr;
+
+ old_ctlr = inb(ctlr_port) & ~IRQ_ACK;
+
+ outb(old_ctlr | IRQ_ACK, ctlr_port);
+ outb(old_ctlr, ctlr_port);
+}
+
+static inline int
+waveartist_sleep(int timeout_ms)
+{
+ unsigned int timeout = timeout_ms * 10 * HZ / 100;
+
+ do {
+ current->state = TASK_INTERRUPTIBLE;
+ timeout = schedule_timeout(timeout);
+ } while (timeout);
+
+ return 0;
+}
+
+static int
+waveartist_reset(wavnc_info *devc)
+{
+ struct address_info *hw = &devc->hw;
+ unsigned int timeout, res = -1;
+
+ waveartist_set_ctlr(hw, -1, RESET);
+ waveartist_sleep(2);
+ waveartist_set_ctlr(hw, RESET, 0);
+
+ timeout = 500;
+ do {
+ mdelay(2);
+
+ if (inb(hw->io_base + STATR) & CMD_RF) {
+ res = inw(hw->io_base + CMDR);
+ if (res == 0x55aa)
+ break;
+ }
+ } while (timeout--);
+
+ if (timeout == 0) {
+ printk("WaveArtist: reset timeout ");
+ if (res != (unsigned int)-1)
+ printk("(res=%04X)", res);
+ printk("\n");
+ return 1;
+ }
+ return 0;
+}
+
+static int
+waveartist_cmd(wavnc_info *devc,
+ int nr_cmd, unsigned int *cmd,
+ int nr_resp, unsigned int *resp)
+{
+ unsigned int io_base = devc->hw.io_base;
+ unsigned int timed_out = 0;
+ unsigned int i;
+
+ if (debug_flg & DEBUG_CMD) {
+ printk("waveartist_cmd: cmd=");
+
+ for (i = 0; i < nr_cmd; i++)
+ printk("%04X ", cmd[i]);
+
+ printk("\n");
+ }
+
+ if (inb(io_base + STATR) & CMD_RF) {
+ int old_data;
+
+ /* flush the port
+ */
+
+ old_data = inw(io_base + CMDR);
+
+ if (debug_flg & DEBUG_CMD)
+ printk("flushed %04X...", old_data);
+
+ udelay(10);
+ }
+
+ for (i = 0; !timed_out && i < nr_cmd; i++) {
+ int count;
+
+ for (count = 5000; count; count--)
+ if (inb(io_base + STATR) & CMD_WE)
+ break;
+
+ if (!count)
+ timed_out = 1;
+ else
+ outw(cmd[i], io_base + CMDR);
+ }
+
+ for (i = 0; !timed_out && i < nr_resp; i++) {
+ int count;
+
+ for (count = 5000; count; count--)
+ if (inb(io_base + STATR) & CMD_RF)
+ break;
+
+ if (!count)
+ timed_out = 1;
+ else
+ resp[i] = inw(io_base + CMDR);
+ }
+
+ if (debug_flg & DEBUG_CMD) {
+ if (!timed_out) {
+ printk("waveartist_cmd: resp=");
+
+ for (i = 0; i < nr_resp; i++)
+ printk("%04X ", resp[i]);
+
+ printk("\n");
+ } else
+ printk("waveartist_cmd: timed out\n");
+ }
+
+ return timed_out ? 1 : 0;
+}
+
+static inline int
+waveartist_cmd2(wavnc_info *devc, unsigned int cmd, unsigned int arg)
+{
+ unsigned int vals[2];
+
+ vals[0] = cmd;
+ vals[1] = arg;
+
+ waveartist_cmd(devc, 2, vals, 1, vals);
+
+ return 0;
+}
+
+static inline int
+waveartist_cmd3(wavnc_info *devc, unsigned int cmd,
+ unsigned int arg1, unsigned int arg2)
+{
+ unsigned int vals[3];
+
+ vals[0] = cmd;
+ vals[1] = arg1;
+ vals[2] = arg2;
+
+ return waveartist_cmd(devc, 3, vals, 0, NULL);
+}
+
+static int
+waveartist_sendcmd(struct address_info *hw, unsigned int cmd)
+{
+ int count;
+
+ if (debug_flg & DEBUG_CMD)
+ printk("waveartist_sendcmd: cmd=0x%04X...", cmd);
+
+ udelay(10);
+
+ if (inb(hw->io_base + STATR) & CMD_RF) {
+ /*
+ * flush the port
+ */
+ count = inw(hw->io_base + CMDR);
+
+ udelay(10);
+
+ if (debug_flg & DEBUG_CMD)
+ printk(" flushed %04X...", count);
+ }
+
+ /*
+ * preset timeout at 5000 loops
+ */
+ count = 5000;
+
+ while (count --)
+ if (inb(hw->io_base + STATR) & CMD_WE) {
+ /* wait till CMD_WE is high
+ * then output the command
+ */
+ outw(cmd, hw->io_base + CMDR);
+ break;
+ }
+
+ /* ready BEFORE timeout?
+ */
+ if (debug_flg & DEBUG_CMD)
+ printk(" %s\n", count ? "Done OK." : "Error!");
+
+ udelay(10);
+
+ return count ? 0 : 1;
+}
+
+static int
+waveartist_getrev(struct address_info *hw, char *rev)
+{
+ int temp;
+
+ waveartist_sendcmd(hw, 0);
+ udelay(20);
+ temp = inw(hw->io_base + CMDR);
+ udelay(20);
+ inw(hw->io_base + CMDR); // discard second word == 0
+
+ rev[0] = temp >> 8;
+ rev[1] = temp & 255;
+ rev[2] = '\0';
+
+ return temp;
+}
+
+inline void
+waveartist_mute(wavnc_info *devc, int mute)
+{
+}
+
+static void waveartist_halt_output(int dev);
+static void waveartist_halt_input(int dev);
+static void waveartist_halt(int dev);
+static void waveartist_trigger(int dev, int state);
+
+static int
+waveartist_open(int dev, int mode)
+{
+ wavnc_info *devc;
+ wavnc_port_info *portc;
+ unsigned long flags;
+
+ if (dev < 0 || dev >= num_audiodevs)
+ return -ENXIO;
+
+ devc = (wavnc_info *) audio_devs[dev]->devc;
+ portc = (wavnc_port_info *) audio_devs[dev]->portc;
+
+ save_flags(flags);
+ cli();
+ if (portc->open_mode || (devc->open_mode & mode)) {
+ restore_flags(flags);
+ return -EBUSY;
+ }
+
+ devc->audio_mode = 0;
+ devc->open_mode |= mode;
+ portc->open_mode = mode;
+ waveartist_trigger(dev, 0);
+
+ if (mode & OPEN_READ)
+ devc->record_dev = dev;
+ if (mode & OPEN_WRITE)
+ devc->playback_dev = dev;
+ restore_flags(flags);
+
+ /*
+ * Mute output until the playback really starts. This
+ * decreases clicking (hope so).
+ */
+ waveartist_mute(devc, 1);
+
+ return 0;
+}
+
+static void
+waveartist_close(int dev)
+{
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ waveartist_halt(dev);
+
+ devc->audio_mode = 0;
+ devc->open_mode &= ~portc->open_mode;
+ portc->open_mode = 0;
+
+ waveartist_mute(devc, 1);
+
+ restore_flags(flags);
+}
+
+static void
+waveartist_output_block(int dev, unsigned long buf, int __count, int intrflag)
+{
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ unsigned long flags;
+ unsigned int count = __count;
+
+ if (debug_flg & DEBUG_OUT)
+ printk("waveartist: output block, buf=0x%lx, count=0x%x...\n",
+ buf, count);
+ /*
+ * 16 bit data
+ */
+ if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE))
+ count >>= 1;
+
+ if (portc->channels > 1)
+ count >>= 1;
+
+ count -= 1;
+
+ if (devc->audio_mode & PCM_ENABLE_OUTPUT &&
+ audio_devs[dev]->flags & DMA_AUTOMODE &&
+ intrflag &&
+ count == devc->xfer_count) {
+ devc->audio_mode |= PCM_ENABLE_OUTPUT;
+ return; /*
+ * Auto DMA mode on. No need to react
+ */
+ }
+
+ save_flags(flags);
+ cli();
+
+ /*
+ * set sample count
+ */
+ waveartist_cmd2(devc, 0x0024, count);
+
+ devc->xfer_count = count;
+ devc->audio_mode |= PCM_ENABLE_OUTPUT;
+
+ restore_flags(flags);
+}
+
+static void
+waveartist_start_input(int dev, unsigned long buf, int __count, int intrflag)
+{
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ unsigned long flags;
+ unsigned int count = __count;
+
+ if (debug_flg & DEBUG_IN)
+ printk("waveartist: start input, buf=0x%lx, count=0x%x...\n",
+ buf, count);
+
+ if (portc->audio_format & (AFMT_S16_LE | AFMT_S16_BE)) /* 16 bit data */
+ count >>= 1;
+
+ if (portc->channels > 1)
+ count >>= 1;
+
+ count -= 1;
+
+ if (devc->audio_mode & PCM_ENABLE_INPUT &&
+ audio_devs[dev]->flags & DMA_AUTOMODE &&
+ intrflag &&
+ count == devc->xfer_count) {
+ devc->audio_mode |= PCM_ENABLE_INPUT;
+ return; /*
+ * Auto DMA mode on. No need to react
+ */
+ }
+
+ save_flags(flags);
+ cli();
+
+ /*
+ * set sample count
+ */
+ waveartist_cmd2(devc, 0x0014, count);
+ waveartist_mute(devc, 0);
+
+ devc->xfer_count = count;
+ devc->audio_mode |= PCM_ENABLE_INPUT;
+
+ restore_flags(flags);
+}
+
+static int
+waveartist_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+ return -EINVAL;
+}
+
+static unsigned int
+waveartist_get_speed(wavnc_port_info *portc)
+{
+ unsigned int speed;
+
+ /*
+ * program the speed, channels, bits
+ */
+ if (portc->speed == 8000)
+ speed = 0x2E71;
+ else if (portc->speed == 11025)
+ speed = 0x4000;
+ else if (portc->speed == 22050)
+ speed = 0x8000;
+ else if (portc->speed == 44100)
+ speed = 0x0;
+ else {
+ /*
+ * non-standard - just calculate
+ */
+ speed = portc->speed << 16;
+
+ speed = (speed / 44100) & 65535;
+ }
+
+ return speed;
+}
+
+static unsigned int
+waveartist_get_bits(wavnc_port_info *portc)
+{
+ unsigned int bits;
+
+ if (portc->audio_format == AFMT_S16_LE)
+ bits = 1;
+ else if (portc->audio_format == AFMT_S8)
+ bits = 0;
+ else
+ bits = 2; //default AFMT_U8
+
+ return bits;
+}
+
+static int
+waveartist_prepare_for_input(int dev, int bsize, int bcount)
+{
+ unsigned long flags;
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+ unsigned int speed, bits;
+
+ if (devc->audio_mode)
+ return 0;
+
+ speed = waveartist_get_speed(portc);
+ bits = waveartist_get_bits(portc);
+
+ save_flags(flags);
+ cli();
+
+ if (waveartist_cmd2(devc, WACMD_INPUTFORMAT, bits))
+ printk("waveartist: error setting the record format to %d\n",
+ portc->audio_format);
+
+ if (waveartist_cmd2(devc, WACMD_INPUTCHANNELS, portc->channels))
+ printk("waveartist: error setting record to %d channels\n",
+ portc->channels);
+
+ /*
+ * write cmd SetSampleSpeedTimeConstant
+ */
+ if (waveartist_cmd2(devc, WACMD_INPUTSPEED, speed))
+ printk("waveartist: error setting the record speed "
+ "to %dHz.\n", portc->speed);
+
+ if (waveartist_cmd2(devc, WACMD_INPUTDMA, 1))
+ printk("waveartist: error setting the record data path "
+ "to 0x%X\n", 1);
+
+ if (waveartist_cmd2(devc, WACMD_INPUTFORMAT, bits))
+ printk("waveartist: error setting the record format to %d\n",
+ portc->audio_format);
+
+ devc->xfer_count = 0;
+ restore_flags(flags);
+ waveartist_halt_input(dev);
+
+ if (debug_flg & DEBUG_INTR) {
+ printk("WA CTLR reg: 0x%02X.\n",inb(devc->hw.io_base + CTLR));
+ printk("WA STAT reg: 0x%02X.\n",inb(devc->hw.io_base + STATR));
+ printk("WA IRQS reg: 0x%02X.\n",inb(devc->hw.io_base + IRQSTAT));
+ }
+
+ return 0;
+}
+
+static int
+waveartist_prepare_for_output(int dev, int bsize, int bcount)
+{
+ unsigned long flags;
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+ unsigned int speed, bits;
+
+ /*
+ * program the speed, channels, bits
+ */
+ speed = waveartist_get_speed(portc);
+ bits = waveartist_get_bits(portc);
+
+ save_flags(flags);
+ cli();
+
+ if (waveartist_cmd2(devc, WACMD_OUTPUTSPEED, speed) &&
+ waveartist_cmd2(devc, WACMD_OUTPUTSPEED, speed))
+ printk("waveartist: error setting the playback speed "
+ "to %dHz.\n", portc->speed);
+
+ if (waveartist_cmd2(devc, WACMD_OUTPUTCHANNELS, portc->channels))
+ printk("waveartist: error setting the playback to"
+ " %d channels\n", portc->channels);
+
+ if (waveartist_cmd2(devc, WACMD_OUTPUTDMA, 0))
+ printk("waveartist: error setting the playback data path "
+ "to 0x%X\n", 0);
+
+ if (waveartist_cmd2(devc, WACMD_OUTPUTFORMAT, bits))
+ printk("waveartist: error setting the playback format to %d\n",
+ portc->audio_format);
+
+ devc->xfer_count = 0;
+ restore_flags(flags);
+ waveartist_halt_output(dev);
+
+ if (debug_flg & DEBUG_INTR) {
+ printk("WA CTLR reg: 0x%02X.\n",inb(devc->hw.io_base + CTLR));
+ printk("WA STAT reg: 0x%02X.\n",inb(devc->hw.io_base + STATR));
+ printk("WA IRQS reg: 0x%02X.\n",inb(devc->hw.io_base + IRQSTAT));
+ }
+
+ return 0;
+}
+
+static void
+waveartist_halt(int dev)
+{
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+ wavnc_info *devc;
+
+
+ if (portc->open_mode & OPEN_WRITE)
+ waveartist_halt_output(dev);
+
+ if (portc->open_mode & OPEN_READ)
+ waveartist_halt_input(dev);
+
+ devc = (wavnc_info *) audio_devs[dev]->devc;
+ devc->audio_mode = 0;
+}
+
+static void
+waveartist_halt_input(int dev)
+{
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ waveartist_mute(devc, 1);
+
+//RMK disable_dma(audio_devs[dev]->dmap_in->dma);
+
+ /*
+ * Stop capture
+ */
+ waveartist_sendcmd(&devc->hw, 0x17);
+
+//RMK enable_dma(audio_devs[dev]->dmap_in->dma);
+ devc->audio_mode &= ~PCM_ENABLE_INPUT;
+
+ /*
+ * Clear interrupt by toggling
+ * the IRQ_ACK bit in CTRL
+ */
+ if (inb(devc->hw.io_base + STATR) & IRQ_REQ)
+ waveartist_iack(devc);
+
+// devc->audio_mode &= ~PCM_ENABLE_INPUT;
+
+ restore_flags(flags);
+}
+
+static void
+waveartist_halt_output(int dev)
+{
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ waveartist_mute(devc, 1);
+
+//RMK disable_dma(audio_devs[dev]->dmap_out->dma);
+
+ waveartist_sendcmd(&devc->hw, 0x27);
+
+//RMK enable_dma(audio_devs[dev]->dmap_out->dma);
+
+ devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
+
+ /*
+ * Clear interrupt by toggling
+ * the IRQ_ACK bit in CTRL
+ */
+ if (inb(devc->hw.io_base + STATR) & IRQ_REQ)
+ waveartist_iack(devc);
+
+// devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
+
+ restore_flags(flags);
+}
+
+static void
+waveartist_trigger(int dev, int state)
+{
+ wavnc_info *devc = (wavnc_info *) audio_devs[dev]->devc;
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+ unsigned long flags;
+
+ if (debug_flg & DEBUG_TRIGGER) {
+ printk("wavnc: audio trigger ");
+ if (state & PCM_ENABLE_INPUT)
+ printk("in ");
+ if (state & PCM_ENABLE_OUTPUT)
+ printk("out");
+ printk("\n");
+ }
+
+ save_flags(flags);
+ cli();
+
+ state &= devc->audio_mode;
+
+ if (portc->open_mode & OPEN_READ &&
+ state & PCM_ENABLE_INPUT)
+ /*
+ * enable ADC Data Transfer to PC
+ */
+ waveartist_sendcmd(&devc->hw, 0x15);
+
+ if (portc->open_mode & OPEN_WRITE &&
+ state & PCM_ENABLE_OUTPUT)
+ /*
+ * enable DAC data transfer from PC
+ */
+ waveartist_sendcmd(&devc->hw, 0x25);
+
+ waveartist_mute(devc, 0);
+
+ restore_flags(flags);
+}
+
+static int
+waveartist_set_speed(int dev, int arg)
+{
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+
+ if (arg <= 0)
+ return portc->speed;
+
+ if (arg < 5000)
+ arg = 5000;
+ if (arg > 44100)
+ arg = 44100;
+
+ portc->speed = arg;
+ return portc->speed;
+
+}
+
+static short
+waveartist_set_channels(int dev, short arg)
+{
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+
+ if (arg != 1 && arg != 2)
+ return portc->channels;
+
+ portc->channels = arg;
+ return arg;
+}
+
+static unsigned int
+waveartist_set_bits(int dev, unsigned int arg)
+{
+ wavnc_port_info *portc = (wavnc_port_info *) audio_devs[dev]->portc;
+
+ if (arg == 0)
+ return portc->audio_format;
+
+ if ((arg != AFMT_U8) && (arg != AFMT_S16_LE) && (arg != AFMT_S8))
+ arg = AFMT_U8;
+
+ portc->audio_format = arg;
+
+ return arg;
+}
+
+static struct audio_driver waveartist_audio_driver = {
+ waveartist_open,
+ waveartist_close,
+ waveartist_output_block,
+ waveartist_start_input,
+ waveartist_ioctl,
+ waveartist_prepare_for_input,
+ waveartist_prepare_for_output,
+ waveartist_halt,
+ NULL,
+ NULL,
+ waveartist_halt_input,
+ waveartist_halt_output,
+ waveartist_trigger,
+ waveartist_set_speed,
+ waveartist_set_bits,
+ waveartist_set_channels
+};
+
+
+static void
+waveartist_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ wavnc_info *devc = (wavnc_info *)dev_id;
+ int irqstatus, status;
+
+ irqstatus = inb(devc->hw.io_base + IRQSTAT);
+ status = inb(devc->hw.io_base + STATR);
+
+ if (debug_flg & DEBUG_INTR)
+ printk("waveartist_intr: stat=%02x, irqstat=%02x\n",
+ status, irqstatus);
+
+ if (status & IRQ_REQ) /* Clear interrupt */
+ waveartist_iack(devc);
+ else
+ printk("waveartist: unexpected interrupt\n");
+
+#ifdef CONFIG_AUDIO
+ if (irqstatus & 0x01) {
+ int temp = 1;
+
+ /* PCM buffer done
+ */
+ if ((status & DMA0) && (devc->audio_mode & PCM_ENABLE_OUTPUT)) {
+ DMAbuf_outputintr(devc->playback_dev, 1);
+ temp = 0;
+ }
+ if ((status & DMA1) && (devc->audio_mode & PCM_ENABLE_INPUT)) {
+ DMAbuf_inputintr(devc->record_dev);
+ temp = 0;
+ }
+ if (temp) //default:
+ printk("WaveArtist: Unknown interrupt\n");
+ }
+#endif
+ if (irqstatus & 0x2)
+ // We do not use SB mode natively...
+ printk("WaveArtist: Unexpected SB interrupt...\n");
+}
+
+/* -------------------------------------------------------------------------
+ * Mixer stuff
+ */
+static void
+waveartist_mixer_update(wavnc_info *devc, int whichDev)
+{
+ unsigned int mask, reg_l, reg_r;
+ unsigned int lev_left, lev_right;
+ unsigned int vals[3];
+
+ lev_left = devc->levels[whichDev] & 0xff;
+ lev_right = devc->levels[whichDev] >> 8;
+
+#define SCALE(lev,max) ((lev) * (max) / 100)
+
+ switch(whichDev) {
+ case SOUND_MIXER_VOLUME:
+ mask = 0x000e;
+ reg_l = 0x200;
+ reg_r = 0x600;
+ lev_left = SCALE(lev_left, 7) << 1;
+ lev_right = SCALE(lev_right, 7) << 1;
+ break;
+
+ case SOUND_MIXER_LINE:
+ mask = 0x07c0;
+ reg_l = 0x000;
+ reg_r = 0x400;
+ lev_left = SCALE(lev_left, 31) << 6;
+ lev_right = SCALE(lev_right, 31) << 6;
+ break;
+
+ case SOUND_MIXER_MIC:
+ mask = 0x0030;
+ reg_l = 0x200;
+ reg_r = 0x600;
+ lev_left = SCALE(lev_left, 3) << 4;
+ lev_right = SCALE(lev_right, 3) << 4;
+ break;
+
+ case SOUND_MIXER_RECLEV:
+ mask = 0x000f;
+ reg_l = 0x300;
+ reg_r = 0x700;
+ lev_left = SCALE(lev_left, 10);
+ lev_right = SCALE(lev_right, 10);
+ break;
+
+ case SOUND_MIXER_LINE1:
+ mask = 0x003e;
+ reg_l = 0x000;
+ reg_r = 0x400;
+ lev_left = SCALE(lev_left, 31) << 1;
+ lev_right = SCALE(lev_right, 31) << 1;
+ break;
+
+ case SOUND_MIXER_PCM:
+ waveartist_cmd3(devc, 0x0031, SCALE(lev_left, 32767),
+ SCALE(lev_right, 32767));
+ return;
+
+ case SOUND_MIXER_SYNTH:
+ waveartist_cmd3(devc, 0x0131, SCALE(lev_left, 32767),
+ SCALE(lev_right, 32767));
+ return;
+
+ default:
+ return;
+ }
+
+ /* read left setting */
+ vals[0] = reg_l + 0x30;
+ waveartist_cmd(devc, 1, vals, 1, vals + 1);
+
+ /* read right setting */
+ vals[0] = reg_r + 0x30;
+ waveartist_cmd(devc, 1, vals, 1, vals + 2);
+
+ vals[1] = (vals[1] & ~mask) | (lev_left & mask);
+ vals[2] = (vals[2] & ~mask) | (lev_right & mask);
+
+ /* write left,right back */
+ vals[0] = 0x32;
+ waveartist_cmd(devc, 3, vals, 0, NULL);
+}
+
+static void
+waveartist_select_input(wavnc_info *devc, unsigned int input)
+{
+ unsigned int vals[3];
+#if 1
+ /* New mixer programming - switch recording source
+ * using R/L_ADC_Mux_Select. We are playing with
+ * left/right mux bit fields in reg 9.
+ *
+ * We can not switch Mux_Select while recording, so
+ * for microphones, enable both left and right and
+ * play with levels only!
+ *
+ * Unfortunately, we need to select the src of mono
+ * recording (left or right) before starting the
+ * recording - so can not dynamically switch between
+ * handset amd internal microphones...
+ */
+
+ /*
+ * Get reg 9
+ */
+ vals[0] = 0x0830;
+ waveartist_cmd(devc, 1, vals, 1, vals + 1);
+
+ /*
+ * Get reg 10, only so that we can write it back.
+ */
+ vals[0] = 0x0930;
+ waveartist_cmd(devc, 1, vals, 1, vals + 2);
+
+ if (debug_flg & DEBUG_MIXER)
+ printk("RECSRC: old left: 0x%04X, old right: 0x%04X.\n",
+ vals[1] & 0x07, (vals[1] >> 3) & 0x07);
+
+ vals[1] &= ~0x03F; //kill current left/right mux input select
+
+ switch (input) {
+ /*
+ * Handset or internal MIC
+ */
+ case SOUND_MASK_MIC:
+ /*
+ * handset not plugged in?
+ */
+ if (devc->handset_state & VNC_INTERNAL_MIC) {
+ /*
+ * set mono recording from right mic
+ */
+ waveartist_sendcmd(&devc->hw, 0x0134);
+#if 0
+ /*
+ * right=mic, left=none
+ */
+ vals[1] |= 0x0028;
+ /*
+ * pretend int mic
+ */
+ devc->rec_devices |= SOUND_MASK_SPEAKER;
+#endif
+ } else {
+ /*
+ * set mono rec from left mic
+ */
+ waveartist_sendcmd(&devc->hw, 0x0034);
+#if 0
+ /*
+ * right=none, left=mic
+ */
+ vals[1] |= 0x0005;
+ /*
+ * show no int mic
+ */
+ devc->rec_devices &= ~SOUND_MASK_SPEAKER;
+#endif
+ }
+ /*
+ * right=mic, left=mic
+ */
+ vals[1] |= 0x002D;
+ break;
+
+ case SOUND_MASK_LINE1:
+ /*
+ * set mono rec from left aux1
+ */
+ waveartist_sendcmd(&devc->hw, 0x0034);
+ /*
+ * right=none, left=Aux1;
+ */
+ vals[1] |= 0x0004;
+ break;
+
+ case SOUND_MASK_LINE:
+ /*
+ * set mono rec from left (default)
+ */
+ waveartist_sendcmd(&devc->hw, 0x0034);
+ /*
+ * right=Line, left=Line;
+ */
+ vals[1] |= 0x0012;
+ break;
+ }
+
+ if (debug_flg & DEBUG_MIXER)
+ printk("RECSRC %d: left=0x%04X, right=0x%04X.\n", input,
+ vals[1] & 0x07, (vals[1] >> 3) & 0x07);
+
+#else
+ /* This part is good, if input connected to
+ * a mixer, so can be used for record-only modes...
+ */
+
+ /*
+ * get reg 4
+ */
+ vals[0] = 0x0330;
+ waveartist_cmd(devc, 1, vals, 1, vals + 1);
+
+ /*
+ * get reg 8
+ */
+ vals[0] = 0x0730;
+ waveartist_cmd(devc, 1, vals, 1, vals + 2);
+
+ if (debug_flg & DEBUG_MIXER)
+ printk("RECSRC: old left: 0x%04X, old right: 0x%04X.\n",
+ vals[1], vals[2]);
+
+ /*
+ * kill current left/right mux input select
+ */
+ vals[1] &= ~0x07F8;
+ vals[2] &= ~0x07F8;
+
+ switch (input) {
+ /*
+ * handset or internal mic
+ */
+ case SOUND_MASK_MIC:
+ /*
+ * handset not plugged in?
+ */
+ if (devc->handset_state & VNC_INTERNAL_MIC) {
+ /*
+ * set mono recording from right mic
+ */
+ waveartist_sendcmd(&devc->hw, 0x0134);
+ /*
+ * left = none, right = mic, RX filter gain
+ */
+ vals[1] |= 0x0C00;
+ vals[2] |= 0x0C88;
+ /*
+ * pretend int mic
+ */
+ devc->rec_devices |= SOUND_MASK_SPEAKER;
+ } else {
+ /*
+ * set mono rec from left mic
+ */
+ waveartist_sendcmd(&devc->hw, 0x0034);
+ /*
+ * left = mic, RX filter gain, right = none;
+ */
+ vals[1] |= 0x0C88;
+ vals[2] |= 0x0C00;
+ /*
+ * show no int mic
+ */
+ devc->rec_devices &= ~SOUND_MASK_SPEAKER;
+ }
+ break;
+
+ case SOUND_MASK_LINE1:
+ /*
+ * set mono rec from left aux1
+ */
+ waveartist_sendcmd(&devc->hw, 0x0034);
+ /*
+ * left = Aux1, right = none
+ */
+ vals[1] |= 0x0C40;
+ vals[2] |= 0x0C00;
+ break;
+
+ case SOUND_MASK_LINE:
+ /*
+ * left = Line, right = Line
+ */
+ vals[1] |= 0x0C10;
+ vals[2] |= 0x0C10;
+ break;
+ }
+
+ if (debug_flg & DEBUG_MIXER)
+ printk("RECSRC %d: left(4) 0x%04X, right(8) 0x%04X.\n",
+ level, vals[1], vals[2]);
+#endif
+ /*
+ * and finally - write the reg pair back....
+ */
+ vals[0] = 0x32;
+
+ waveartist_cmd(devc, 3, vals, 0, NULL);
+}
+
+static int
+waveartist_mixer_set(wavnc_info *devc, int whichDev, unsigned int level)
+{
+ unsigned int lev_left = level & 0x007f;
+ unsigned int lev_right = (level & 0x7f00) >> 8;
+
+ int left, right, devmask, changed, i;
+
+ left = level & 0x7f;
+ right = (level & 0x7f00) >> 8;
+
+ if (debug_flg & DEBUG_MIXER)
+ printk("wa_mixer_set(dev=%d, level=%X)\n",
+ whichDev, level);
+
+ switch (whichDev) {
+ /* Master volume (0-7)
+ * We have 3 bits on the Left/Right Mixer Gain,
+ * bits 3,2,1 on 3 and 7
+ */
+ case SOUND_MIXER_VOLUME:
+ devc->levels[whichDev] = lev_left | lev_right << 8;
+ waveartist_mixer_update(devc, whichDev);
+ break;
+
+
+ /* External line (0-31)
+ * use LOUT/ROUT bits 10...6, reg 1 and 5
+ */
+ case SOUND_MIXER_LINE:
+ devc->levels[whichDev] = lev_left | lev_right << 8;
+ waveartist_mixer_update(devc, whichDev);
+ break;
+
+ /* Mono microphone (0-3) mute,
+ * 0db,10db,20db
+ */
+ case SOUND_MIXER_MIC:
+#if 1
+ devc->levels[whichDev] = lev_left | lev_right << 8;
+#else
+ /* we do not need to mute volume of
+ * an unused mic - it is simply unused...
+ */
+ if (devc->handset_state & VNC_INTERNAL_MIC)
+ devc->levels[whichDev] = lev_right << 8;
+ else
+ levels[whichDev] = lev_left;
+#endif
+ waveartist_mixer_update(devc, whichDev);
+ break;
+
+ /* Recording level (0-7)
+ */
+ case SOUND_MIXER_RECLEV:
+ devc->levels[whichDev] = lev_left | lev_right << 8;
+ waveartist_mixer_update(devc, whichDev);
+ break;
+
+ /* Mono External Aux1 (0-31)
+ * use LINE1 bits 5...1, reg 1 and 5
+ */
+ case SOUND_MIXER_LINE1:
+ devc->levels[whichDev] = lev_left | lev_right << 8;
+ waveartist_mixer_update(devc, whichDev);
+ break;
+
+ /* WaveArtist PCM (0-32767)
+ */
+ case SOUND_MIXER_PCM:
+ devc->levels[whichDev] = lev_left | lev_right << 8;
+ waveartist_mixer_update(devc, whichDev);
+ break;
+
+ /* Internal synthesizer (0-31)
+ */
+ case SOUND_MIXER_SYNTH:
+ devc->levels[whichDev] = lev_left | lev_right << 8;
+ waveartist_mixer_update(devc, whichDev);
+ break;
+
+
+ /* Select recording input source
+ */
+ case SOUND_MIXER_RECSRC:
+ devmask = level & POSSIBLE_RECORDING_DEVICES;
+
+ changed = devmask ^ devc->recmask;
+ devc->recmask = devmask;
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ if (changed & (1 << i))
+ waveartist_mixer_update(devc, i);
+
+ waveartist_select_input(devc, level);
+ /*
+ * do not save in "levels", return current setting
+ */
+ return devc->recmask;
+
+ default:
+ return -EINVAL;
+ }
+
+ return devc->levels[whichDev];
+}
+
+static void
+waveartist_mixer_reset(wavnc_info *devc)
+{
+ int i;
+
+ if (debug_flg & DEBUG_MIXER)
+ printk("%s: mixer_reset\n", devc->hw.name);
+
+ /*
+ * reset mixer cmd
+ */
+ waveartist_sendcmd(&devc->hw, 0x33);
+
+ /*
+ * set input for ADC to come from
+ * a mux (left and right) == reg 9,
+ * initially none
+ */
+ waveartist_cmd3(devc, 0x0032, 0x9800, 0xa836);
+
+ /*
+ * set mixer input select to none, RX filter gains 0 db
+ */
+ waveartist_cmd3(devc, 0x0032, 0x4c00, 0x8c00);
+
+ /*
+ * set bit 0 reg 2 to 1 - unmute MonoOut
+ */
+ waveartist_cmd3(devc, 0x0032, 0x2801, 0x6800);
+
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
+ waveartist_mixer_update(devc, i);
+
+ /* set default input device = internal mic
+ * current recording device = none
+ * no handset
+ */
+ devc->recmask = 0;
+ devc->handset_state = VNC_INTERNAL_MIC;
+// waveartist_mixer_set(devc, SOUND_MIXER_RECSRC, SOUND_MASK_MIC);
+
+ /*
+ * start from enabling the hw setting
+ */
+ devc->handset_mute_sw = 0;
+ devc->supported_devices = SUPPORTED_MIXER_DEVICES;
+ devc->rec_devices = POSSIBLE_RECORDING_DEVICES;
+}
+
+static int
+waveartist_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+ wavnc_info *devc = (wavnc_info *)audio_devs[dev]->devc;
+#if 0
+ //use this call to override the automatic handset behaviour - ignore handset
+ //bit 0x80 = total control over handset - do not react to plug/unplug
+ //bit 0x10 = 1 == internal mic, otherwise handset mic
+ //bit 0x01 = 1 == mute internal speaker, otherwise unmute
+
+ if (cmd == SOUND_MIXER_PRIVATE1) {
+ int val, temp;
+
+ val = *(int *) arg;
+
+// printk("MIXER_PRIVATE1: passed parameter = 0x%X.\n",val);
+ return -EINVAL; //check if parameter is logical...
+
+ devc->soft_mute_flag = val;
+
+ temp = val & VNC_INTERNAL_SPKR;
+ if (temp != devc->mute_state) {
+// printk("MIXER_PRIVATE1: mute_mono(0x%X).\n",temp);
+ vnc_mute(devc, temp);
+ }
+
+// temp = devc->handset_state;
+
+ // do not check if it is not already in
+ // the right setting, since we are
+ // laying about the current state...
+
+// if ((val & VNC_INTERNAL_MIC) != temp) {
+ devc->handset_state = val & VNC_INTERNAL_MIC;
+// printk("MIXER_PRIVATE1: mixer_set(0x%X).\n",devc->handset_state);
+ wa_mixer_set(devc, SOUND_MIXER_RECSRC, SOUND_MASK_MIC);
+// devc->handset_state = temp;
+ }
+ return 0;
+ }
+#if 0
+ if (cmd == SOUND_MIXER_PRIVATE2) {
+#define VNC_SOUND_PAUSE 0x53 //to pause the DSP
+#define VNC_SOUND_RESUME 0x57 //to unpause the DSP
+ int val;
+
+ val = *(int *) arg;
+
+ printk("MIXER_PRIVATE2: passed parameter = 0x%X.\n",val);
+
+ if (val == VNC_SOUND_PAUSE) {
+ wa_sendcmd(0x16); //PAUSE the ADC
+ } else if (val == VNC_SOUND_RESUME) {
+ wa_sendcmd(0x18); //RESUME the ADC
+ } else {
+ return -EINVAL; //invalid parameters...
+ }
+ return 0;
+ }
+#endif
+
+ if (cmd == SOUND_MIXER_PRIVATE3) {
+ long unsigned flags;
+ int mixer_reg[15]; //reg 14 is actually a command: read,write,reset
+
+ int val;
+ int i;
+
+ val = *(int *) arg;
+
+ if (verify_area(VERIFY_READ, (void *) val, sizeof(mixer_reg) == -EFAULT))
+ return (-EFAULT);
+
+ memcpy_fromfs(&mixer_reg, (void *) val, sizeof(mixer_reg));
+
+ if (mixer_reg[0x0E] == MIXER_PRIVATE3_RESET) { //reset command??
+ wavnc_mixer_reset(devc);
+ return (0);
+ } else if (mixer_reg[0x0E] == MIXER_PRIVATE3_WRITE) { //write command??
+// printk("WaveArtist Mixer: Private write command.\n");
+
+ wa_sendcmd(0x32); //Pair1 - word 1 and 5
+ wa_sendcmd(mixer_reg[0]);
+ wa_sendcmd(mixer_reg[4]);
+
+ wa_sendcmd(0x32); //Pair2 - word 2 and 6
+ wa_sendcmd(mixer_reg[1]);
+ wa_sendcmd(mixer_reg[5]);
+
+ wa_sendcmd(0x32); //Pair3 - word 3 and 7
+ wa_sendcmd(mixer_reg[2]);
+ wa_sendcmd(mixer_reg[6]);
+
+ wa_sendcmd(0x32); //Pair4 - word 4 and 8
+ wa_sendcmd(mixer_reg[3]);
+ wa_sendcmd(mixer_reg[7]);
+
+ wa_sendcmd(0x32); //Pair5 - word 9 and 10
+ wa_sendcmd(mixer_reg[8]);
+ wa_sendcmd(mixer_reg[9]);
+
+ wa_sendcmd(0x0031); //set left and right PCM
+ wa_sendcmd(mixer_reg[0x0A]);
+ wa_sendcmd(mixer_reg[0x0B]);
+
+ wa_sendcmd(0x0131); //set left and right FM
+ wa_sendcmd(mixer_reg[0x0C]);
+ wa_sendcmd(mixer_reg[0x0D]);
+
+ return 0;
+ } else if (mixer_reg[0x0E] == MIXER_PRIVATE3_READ) { //read command?
+// printk("WaveArtist Mixer: Private read command.\n");
+
+ //first read all current values...
+ save_flags(flags);
+ cli();
+
+ for (i = 0; i < 14; i++) {
+ wa_sendcmd((i << 8) + 0x30); // get ready for command nn30H
+
+ while (!(inb(STATR) & CMD_RF)) {
+ }; //wait for response ready...
+
+ mixer_reg[i] = inw(CMDR);
+ }
+ restore_flags(flags);
+
+ if (verify_area(VERIFY_WRITE, (void *) val, sizeof(mixer_reg) == -EFAULT))
+ return (-EFAULT);
+
+ memcpy_tofs((void *) val, &mixer_reg, sizeof(mixer_reg));
+ return 0;
+ } else
+ return -EINVAL;
+ }
+#endif
+ if (((cmd >> 8) & 0xff) == 'M') {
+ if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
+ int val;
+
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+
+ /*
+ * special case for master volume: if we
+ * received this call - switch from hw
+ * volume control to a software volume
+ * control, till the hw volume is modified
+ * to signal that user wants to be back in
+ * hardware...
+ */
+ if ((cmd & 0xff) == SOUND_MIXER_VOLUME)
+ devc->use_slider = 0;
+
+ return waveartist_mixer_set(devc, cmd & 0xff, val);
+ } else {
+ int ret;
+
+ /*
+ * Return parameters
+ */
+ switch (cmd & 0xff) {
+ case SOUND_MIXER_RECSRC:
+ ret = devc->recmask;
+
+ if (devc->handset_state & VNC_INTERNAL_MIC)
+ ret |= SOUND_MASK_SPEAKER;
+ break;
+
+ case SOUND_MIXER_DEVMASK:
+ ret = devc->supported_devices;
+ break;
+
+ case SOUND_MIXER_STEREODEVS:
+ ret = devc->supported_devices &
+ ~(SOUND_MASK_SPEAKER|SOUND_MASK_IMIX);
+ break;
+
+ case SOUND_MIXER_RECMASK:
+ ret = devc->rec_devices;
+ break;
+
+ case SOUND_MIXER_CAPS:
+ ret = SOUND_CAP_EXCL_INPUT;
+ break;
+
+ default:
+ if ((cmd & 0xff) < SOUND_MIXER_NRDEVICES)
+ ret = devc->levels[cmd & 0xff];
+ else
+ return -EINVAL;
+ }
+
+ return put_user(ret, (int *)arg) ? -EINVAL : 0;
+ }
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+static struct mixer_operations waveartist_mixer_operations =
+{
+ "WaveArtist",
+ "WaveArtist NetWinder",
+ waveartist_mixer_ioctl
+};
+
+static int
+waveartist_init(wavnc_info *devc)
+{
+ wavnc_port_info *portc;
+ char rev[3], dev_name[64];
+ int my_dev;
+
+ waveartist_reset(devc);
+
+ sprintf(dev_name, "%s (%s", devc->hw.name, devc->chip_name);
+
+ if (waveartist_getrev(&devc->hw, rev)) {
+ strcat(dev_name, " rev. ");
+ strcat(dev_name, rev);
+ }
+ strcat(dev_name, ")");
+
+ conf_printf2(dev_name, devc->hw.io_base, devc->hw.irq,
+ devc->hw.dma, devc->hw.dma2);
+
+ portc = (wavnc_port_info *)kmalloc(sizeof(wavnc_port_info), GFP_KERNEL);
+ if (portc == NULL)
+ goto nomem;
+
+ memset(portc, 0, sizeof(wavnc_port_info));
+
+ my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION, dev_name,
+ &waveartist_audio_driver, sizeof(struct audio_driver),
+ devc->audio_flags, AFMT_U8 | AFMT_S16_LE | AFMT_S8,
+ devc, devc->hw.dma, devc->hw.dma2);
+
+ if (my_dev < 0)
+ goto free;
+
+ audio_devs[my_dev]->portc = portc;
+
+ waveartist_mixer_reset(devc);
+
+ /*
+ * clear any pending interrupt
+ */
+ waveartist_iack(devc);
+
+ if (request_irq(devc->hw.irq, waveartist_intr, 0, devc->hw.name, devc) < 0) {
+ printk("%s: IRQ %d in use\n",
+ devc->hw.name, devc->hw.irq);
+ goto uninstall;
+ }
+
+ if (sound_alloc_dma(devc->hw.dma, devc->hw.name)) {
+ printk("%s: Can't allocate DMA%d\n",
+ devc->hw.name, devc->hw.dma);
+ goto uninstall_irq;
+ }
+
+ if (devc->hw.dma != devc->hw.dma2 && devc->hw.dma2 != NO_DMA)
+ if (sound_alloc_dma(devc->hw.dma2, devc->hw.name)) {
+ printk("%s: can't allocate DMA%d\n",
+ devc->hw.name, devc->hw.dma2);
+ goto uninstall_dma;
+ }
+
+ waveartist_set_ctlr(&devc->hw, 0, DMA1_IE | DMA0_IE);
+
+ audio_devs[my_dev]->mixer_dev =
+ sound_install_mixer(MIXER_DRIVER_VERSION,
+ dev_name,
+ &waveartist_mixer_operations,
+ sizeof(struct mixer_operations),
+ devc);
+
+ return my_dev;
+
+uninstall_dma:
+ sound_free_dma(devc->hw.dma);
+
+uninstall_irq:
+ free_irq(devc->hw.irq, devc);
+
+uninstall:
+ sound_unload_audiodev(my_dev);
+
+free:
+ kfree(portc);
+
+nomem:
+ return -1;
+}
+
+/*
+ * Corel Netwinder specifics...
+ */
+static void
+vnc_mute(wavnc_info *devc, int mute)
+{
+ extern spinlock_t gpio_lock;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+ cpld_modify(CPLD_UNMUTE, mute ? 0 : CPLD_UNMUTE);
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ devc->mute_state = mute;
+}
+
+static int
+vnc_volume_slider(wavnc_info *devc)
+{
+ static signed int old_slider_volume;
+ unsigned long flags;
+ signed int volume = 255;
+
+ *CSR_TIMER1_LOAD = 0x00ffffff;
+
+ save_flags(flags);
+ cli();
+
+ outb(0xFF, 0x201);
+ *CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV1;
+
+ while (volume && (inb(0x201) & 0x01))
+ volume--;
+
+ *CSR_TIMER1_CNTL = 0;
+
+ restore_flags(flags);
+
+ volume = 0x00ffffff - *CSR_TIMER1_VALUE;
+
+
+#ifndef REVERSE
+ volume = 150 - (volume >> 5);
+#else
+ volume = (volume >> 6) - 25;
+#endif
+
+ if (volume < 0)
+ volume = 0;
+
+ if (volume > 100)
+ volume = 100;
+
+ /*
+ * slider quite often reads +-8, so debounce this random noise
+ */
+ if ((volume - old_slider_volume) > 7 ||
+ (old_slider_volume - volume) > 7) {
+ old_slider_volume = volume;
+
+ DEB(printk("Slider volume: %d.\n", old_slider_volume));
+ }
+
+ return old_slider_volume;
+}
+
+static int
+vnc_slider(wavnc_info *devc)
+{
+ signed int slider_volume;
+ unsigned int temp;
+
+ /*
+ * read the "buttons" state.
+ * Bit 4 = handset present,
+ * Bit 5 = offhook
+ */
+ // the state should be "querable" via a private IOCTL call
+ temp = inb(0x201) & 0x30;
+
+ if (!devc->handset_mute_sw &&
+ (temp ^ devc->handset_state) & VNC_INTERNAL_MIC) {
+ devc->handset_state = temp;
+ devc->handset_mute_sw = 0;
+
+ vnc_mute(devc, (temp & VNC_INTERNAL_MIC) ? 1 : 0);
+ }
+
+ slider_volume = vnc_volume_slider(devc);
+
+ /*
+ * If we're using software controlled volume, and
+ * the slider moves by more than 20%, then we
+ * switch back to slider controlled volume.
+ */
+ if (devc->slider_vol > slider_volume) {
+ if (devc->slider_vol - slider_volume > 20)
+ devc->use_slider = 1;
+ } else {
+ if (slider_volume - devc->slider_vol > 20)
+ devc->use_slider = 1;
+ }
+
+ /*
+ * use only left channel
+ */
+ temp = levels[SOUND_MIXER_VOLUME] & 0xFF;
+
+ if (slider_volume != temp && devc->use_slider) {
+ devc->slider_vol = slider_volume;
+
+ waveartist_mixer_set(devc, SOUND_MIXER_VOLUME,
+ slider_volume | slider_volume << 8);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static void
+vnc_slider_tick(unsigned long data)
+{
+ int next_timeout;
+
+ if (vnc_slider(adev_info + data))
+ next_timeout = 5; // mixer reported change
+ else
+ next_timeout = VNC_TIMER_PERIOD;
+
+ mod_timer(&vnc_timer, jiffies + next_timeout);
+}
+
+int
+probe_waveartist(struct address_info *hw_config)
+{
+ wavnc_info *devc = &adev_info[nr_waveartist_devs];
+
+ if (nr_waveartist_devs >= MAX_AUDIO_DEV) {
+ printk("waveartist: too many audio devices\n");
+ return 0;
+ }
+
+ if (check_region(hw_config->io_base, 15)) {
+ printk("WaveArtist: I/O port conflict\n");
+ return 0;
+ }
+
+ if (hw_config->irq > 31 || hw_config->irq < 16) {
+ printk("WaveArtist: Bad IRQ %d\n", hw_config->irq);
+ return 0;
+ }
+
+ if (hw_config->dma != 3) {
+ printk("WaveArtist: Bad DMA %d\n", hw_config->dma);
+ return 0;
+ }
+
+ hw_config->name = "WaveArtist";
+ devc->hw = *hw_config;
+ devc->open_mode = 0;
+ devc->chip_name = "RWA-010";
+
+ return 1;
+}
+
+void
+attach_waveartist(struct address_info *hw)
+{
+ wavnc_info *devc = &adev_info[nr_waveartist_devs];
+
+ /*
+ * NOTE! If irq < 0, there is another driver which has allocated the
+ * IRQ so that this driver doesn't need to allocate/deallocate it.
+ * The actually used IRQ is ABS(irq).
+ */
+ devc->hw = *hw;
+ devc->hw.irq = (hw->irq > 0) ? hw->irq : 0;
+ devc->open_mode = 0;
+ devc->playback_dev = 0;
+ devc->record_dev = 0;
+ devc->audio_flags = DMA_AUTOMODE;
+ devc->levels = levels;
+
+ if (hw->dma != hw->dma2 && hw->dma2 != NO_DMA)
+ devc->audio_flags |= DMA_DUPLEX;
+
+ request_region(hw->io_base, 15, devc->hw.name);
+
+ devc->dev_no = waveartist_init(devc);
+
+ if (devc->dev_no < 0)
+ release_region(hw->io_base, 15);
+ else {
+ init_timer(&vnc_timer);
+ vnc_timer.function = vnc_slider_tick;
+ vnc_timer.expires = jiffies;
+ vnc_timer.data = nr_waveartist_devs;
+ add_timer(&vnc_timer);
+
+ nr_waveartist_devs += 1;
+
+ vnc_mute(devc, 0);
+ }
+}
+
+void
+unload_waveartist(struct address_info *hw)
+{
+ wavnc_info *devc = NULL;
+ int i;
+
+ for (i = 0; i < nr_waveartist_devs; i++)
+ if (hw->io_base == adev_info[i].hw.io_base) {
+ devc = adev_info + i;
+ break;
+ }
+
+ if (devc != NULL) {
+ int mixer;
+
+ release_region(devc->hw.io_base, 15);
+
+ waveartist_set_ctlr(&devc->hw, DMA1_IE|DMA0_IE, 0);
+
+ if (devc->hw.irq >= 0)
+ free_irq(devc->hw.irq, devc);
+
+ sound_free_dma(devc->hw.dma);
+
+ if (devc->hw.dma != devc->hw.dma2 &&
+ devc->hw.dma2 != NO_DMA)
+ sound_free_dma(devc->hw.dma2);
+
+ del_timer(&vnc_timer);
+
+ mixer = audio_devs[devc->dev_no]->mixer_dev;
+
+ if (mixer >= 0)
+ sound_unload_mixerdev(mixer);
+
+ if (devc->dev_no >= 0)
+ sound_unload_audiodev(devc->dev_no);
+
+ nr_waveartist_devs -= 1;
+
+ for (; i < nr_waveartist_devs; i++)
+ adev_info[i] = adev_info[i + 1];
+ } else
+ printk("waveartist: can't find device to unload\n");
+}
+
+#ifdef MODULE
+
+MODULE_PARM(io, "i"); /* IO base */
+MODULE_PARM(irq, "i"); /* IRQ */
+MODULE_PARM(dma, "i"); /* DMA */
+MODULE_PARM(dma2, "i"); /* DMA2 */
+
+int io = CONFIG_WAVEARTIST_BASE;
+int irq = CONFIG_WAVEARTIST_IRQ;
+int dma = CONFIG_WAVEARTIST_DMA;
+int dma2 = CONFIG_WAVEARTIST_DMA2;
+
+static int attached;
+
+struct address_info hw_config;
+
+int init_module(void)
+{
+ hw_config.io_base = io;
+ hw_config.irq = irq;
+ hw_config.dma = dma;
+ hw_config.dma2 = dma2;
+
+ if (!probe_waveartist(&hw_config))
+ return -ENODEV;
+
+ attach_waveartist(&hw_config);
+ attached = 1;
+
+ SOUND_LOCK;
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ if (attached) {
+ SOUND_LOCK_END;
+
+ unload_waveartist(&hw_config);
+ }
+}
+#endif
--- /dev/null
+
+// def file for Rockwell RWA010 chip set, as installed in Corel NetWinder
+
+//registers
+#define WA_BASE 0
+//x250
+
+#define CMDR WA_BASE+0
+#define DATR WA_BASE+2
+
+#define CTLR WA_BASE+4
+#define STATR WA_BASE+5
+
+#define IRQSTAT WA_BASE+12
+
+//bit defs
+//reg STATR
+#define CMD_WE 0x80
+#define CMD_RF 0x40
+#define DAT_WE 0x20
+#define DAT_RF 0x10
+
+#define IRQ_REQ 0x08
+#define DMA1 0x04
+#define DMA0 0x02
+
+//bit defs
+//reg CTLR
+#define CMD_WEIE 0x80
+#define CMD_RFIE 0x40
+#define DAT_WEIE 0x20
+#define DAT_RFIE 0x10
+
+#define RESET 0x08
+#define DMA1_IE 0x04
+#define DMA0_IE 0x02
+#define IRQ_ACK 0x01
+
+//commands
+
+#define WACMD_SYSTEMID 0
+#define WACMD_INPUTFORMAT 0x10 //0-8S, 1-16S, 2-8U
+#define WACMD_INPUTCHANNELS 0x11 //1-Mono, 2-Stereo
+#define WACMD_INPUTSPEED 0x12 //sampling rate
+#define WACMD_INPUTDMA 0x13 //0-8bit, 1-16bit, 2-PIO
+#define WACMD_INPUTSIZE 0x14 //samples to interrupt
+#define WACMD_INPUTSTART 0x15 //start ADC
+#define WACMD_INPUTPAUSE 0x16 //pause ADC
+#define WACMD_INPUTSTOP 0x17 //stop ADC
+#define WACMD_INPUTRESUME 0x18 //resume ADC
+#define WACMD_INPUTPIO 0x19 //PIO ADC
+
+#define WACMD_OUTPUTFORMAT 0x20 //0-8S, 1-16S, 2-8U
+#define WACMD_OUTPUTCHANNELS 0x21 //1-Mono, 2-Stereo
+#define WACMD_OUTPUTSPEED 0x22 //sampling rate
+#define WACMD_OUTPUTDMA 0x23 //0-8bit, 1-16bit, 2-PIO
+#define WACMD_OUTPUTSIZE 0x24 //samples to interrupt
+#define WACMD_OUTPUTSTART 0x25 //start ADC
+#define WACMD_OUTPUTPAUSE 0x26 //pause ADC
+#define WACMD_OUTPUTSTOP 0x27 //stop ADC
+#define WACMD_OUTPUTRESUME 0x28 //resume ADC
+#define WACMD_OUTPUTPIO 0x29 //PIO ADC
+
+
+
+
+int wa_sendcmd(unsigned int cmd);
+int wa_writecmd(unsigned int cmd, unsigned int arg);
#include <asm/io.h>
#include <asm/spinlock.h>
+#include <asm/unaligned.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
#include <video/fbcon-cfb24.h>
#include <video/fbcon-cfb32.h>
-#if defined(CONFIG_PPC)
+#if defined(CONFIG_FB_OF)
#if defined(CONFIG_FB_COMPAT_XPMAC)
#include <asm/vc_ioctl.h>
#endif
/* I benchmarked PII/350MHz with G200... MEMCPY, MEMCPYTOIO and WRITEL are on same speed ( <2% diff) */
/* so that means that G200 speed (or AGP speed?) is our limit... I do not have benchmark to test, how */
/* much of PCI bandwidth is used during transfers... */
-#if defined(__i386__) || defined(__ppc__)
+#if defined(__i386__)
#define MEMCPYTOIO_MEMCPY
#else
#define MEMCPYTOIO_WRITEL
#error "Sorry, I have no idea how to do this on sparc... There is mapioaddr... With bus_type parameter..."
#endif
-#ifdef __m68k__
+#if defined(__m68k__)
#define MAP_BUSTOVIRT
#else
+#if defined(CONFIG_PPC) && defined(CONFIG_PREP) && defined(_ISA_MEM_BASE)
+/* do not tell me that PPC is not broken... if ioremap() oops with
+ invalid value written to msr... */
+#define MAP_ISAMEMBASE
+#else
#define MAP_IOREMAP
#endif
+#endif
#ifdef DEBUG
#define dprintk(X...) printk(X)
#ifdef MAP_BUSTOVIRT
virt->vaddr = bus_to_virt(phys);
#else
+#ifdef MAP_ISAMEMBASE
+ virt->vaddr = (void*)(phys + _ISA_MEM_BASE);
+#else
#error "Your architecture does not have neither ioremap nor bus_to_virt... Giving up"
#endif
+#endif
#endif
return (virt->vaddr == 0); /* 0, !0... 0, error_code in future */
}
int inverse;
int hwcursor;
int blink;
+ int sgram;
int accelerator;
int text_type_aux;
} cmap;
#endif
struct { unsigned red, green, blue, transp; } palette[256];
-#if defined(CONFIG_PPC) && defined(CONFIG_FB_COMPAT_XPMAC)
+#if defined(CONFIG_FB_OF) && defined(CONFIG_FB_COMPAT_XPMAC)
char matrox_name[32];
#endif
};
-#if defined(CONFIG_PPC)
-unsigned char nvram_read_byte(int);
-#endif
#if defined(CONFIG_FB_OF)
+unsigned char nvram_read_byte(int);
int matrox_of_init(struct device_node *dp);
#endif
0x00, 0,
M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL,
M1064_XGENCTRL_VS_0 | M1064_XGENCTRL_ALPHA_DIS | M1064_XGENCTRL_BLACK_0IRE | M1064_XGENCTRL_NO_SYNC_ON_GREEN,
- M1064_XMISCCTRL_DAC_EN | M1064_XMISCCTRL_MFC_VGA | M1064_XMISCCTRL_DAC_8BIT | M1064_XMISCCTRL_LUT_EN,
+ M1064_XMISCCTRL_DAC_EN | M1064_XMISCCTRL_MFC_DIS | M1064_XMISCCTRL_DAC_8BIT | M1064_XMISCCTRL_LUT_EN,
0x10, 0x3F, M1064_XZOOMCTRL_1, M1064_XSENSETEST_BCOMP | M1064_XSENSETEST_GCOMP | M1064_XSENSETEST_RCOMP | M1064_XSENSETEST_PDOWN,
0x00,
0x00, 0x00, 0xFF, 0xFF};
memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
if (p->type == FB_TYPE_TEXT) {
hw->DACreg[POS1064_XMISCCTRL] = M1064_XMISCCTRL_DAC_EN
- | M1064_XMISCCTRL_MFC_VGA
+ | M1064_XMISCCTRL_MFC_DIS
| M1064_XMISCCTRL_DAC_6BIT
| M1064_XMISCCTRL_LUT_EN;
hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP
pci_read_config_dword(ACCESS_FBINFO(pcidev), 0x50, ®50);
reg50 &= ~0x3000;
pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50);
- if (!(x7AF4 & 0x10))
- hw->MXoptionReg |= 0x4000;
if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100) {
- hw->MXoptionReg |= 0x1080;
+ hw->MXoptionReg |= 0x5080;
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
mga_outl(M_CTLWTST, 0x01032521);
/* mga_outl(M_CTLWTST, 0x03258A31); */
}
} else {
hw->MXoptionReg |= 0x00000C00;
+ if (ACCESS_FBINFO(devflags.sgram))
+ hw->MXoptionReg |= 0x4000;
mga_outl(M_CTLWTST, 0x042450A1);
mga_outb(0x1E47, 0x00);
mga_outb(0x1E46, 0x00);
ACCESS_FBINFO(newhw) = ohw;
matrox_cfbX_init(PMINFO display);
do_install_cmap(PMINFO display);
-#if defined(CONFIG_PPC) && defined(CONFIG_FB_COMPAT_XPMAC)
+#if defined(CONFIG_FB_OF) && defined(CONFIG_FB_COMPAT_XPMAC)
if (console_fb_info == &ACCESS_FBINFO(fbcon)) {
int vmode, cmode;
display_info.cmap_data_address = 0;
display_info.disp_reg_address = ACCESS_FBINFO(mmio.base);
}
-#endif /* CONFIG_PPC && CONFIG_FB_COMPAT_XPMAC */
+#endif /* CONFIG_FB_OF && CONFIG_FB_COMPAT_XPMAC */
}
}
return 0;
static int inverse = 0; /* "matrox:inverse" */
static int hwcursor = 1; /* "matrox:nohwcursor" */
static int blink = 1; /* "matrox:noblink" */
+static int sgram = 0; /* "matrox:sgram" */
+static int mtrr = 1; /* "matrox:nomtrr" */
static int grayscale = 0; /* "matrox:grayscale" */
static unsigned int fastfont = 0; /* "matrox:fastfont:xxxxx" */
static int dev = -1; /* "matrox:dev:xxxxx" */
disabled = 1;
else if (!strcmp(this_opt, "enabled")) /* noenabled does not exist */
disabled = 0;
+ else if (!strcmp(this_opt, "sgram")) /* nosgram == sdram */
+ sgram = 1;
+ else if (!strcmp(this_opt, "sdram"))
+ sgram = 0;
else {
int value = 1;
nobios = !value;
else if (!strcmp(this_opt, "init"))
noinit = !value;
+ else if (!strcmp(this_opt, "mtrr"))
+ mtrr = value;
else if (!strcmp(this_opt, "inv24"))
inv24 = value;
else if (!strcmp(this_opt, "cross4MB"))
if (ACCESS_FBINFO(video.len_usable) > 0x08000000)
ACCESS_FBINFO(video.len_usable) = 0x08000000;
#ifdef CONFIG_MTRR
- ACCESS_FBINFO(mtrr.vram) = mtrr_add(video_base_phys, ACCESS_FBINFO(video.len), MTRR_TYPE_WRCOMB, 1);
- ACCESS_FBINFO(mtrr.vram_valid) = 1;
- printk(KERN_INFO "matroxfb: MTRR's turned on\n");
+ if (mtrr) {
+ ACCESS_FBINFO(mtrr.vram) = mtrr_add(video_base_phys, ACCESS_FBINFO(video.len), MTRR_TYPE_WRCOMB, 1);
+ ACCESS_FBINFO(mtrr.vram_valid) = 1;
+ printk(KERN_INFO "matroxfb: MTRR's turned on\n");
+ }
#endif /* CONFIG_MTRR */
/* validate params, autodetect k, M */
ACCESS_FBINFO(fbcon.flags) = FBINFO_FLAG_DEFAULT;
ACCESS_FBINFO(hw_switch->reset(PMINFO hw));
ACCESS_FBINFO(video.len_usable) &= PAGE_MASK;
-#if defined(CONFIG_PPC)
+#if defined(CONFIG_FB_OF)
#if defined(CONFIG_FB_COMPAT_XPMAC)
strcpy(ACCESS_FBINFO(matrox_name), "MTRX,"); /* OpenFirmware naming convension */
strncat(ACCESS_FBINFO(matrox_name), b->name, 26);
ACCESS_FBINFO(devflags.precise_width) = option_precise_width;
ACCESS_FBINFO(devflags.hwcursor) = hwcursor;
ACCESS_FBINFO(devflags.blink) = blink;
+ ACCESS_FBINFO(devflags.sgram) = sgram;
ACCESS_FBINFO(capable.cross4MB) = cross4MB;
ACCESS_FBINFO(fastfont.size) = fastfont;
MODULE_PARM_DESC(nobios, "Disables ROM BIOS (0 or 1=disabled) (default=do not change BIOS state)");
MODULE_PARM(noinit, "i");
MODULE_PARM_DESC(noinit, "Disables W/SG/SD-RAM and bus interface initialization (0 or 1=do not initialize) (default=0)");
+MODULE_PARM(mtrr, "i");
+MODULE_PARM_DESC(mtrr, "This speeds up video memory accesses (0=disabled or 1) (default=1)");
+MODULE_PARM(sgram, "i");
+MODULE_PARM_DESC(sgram, "Indicates that G200 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)");
MODULE_PARM(inv24, "i");
MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)");
MODULE_PARM(inverse, "i");
*/
static unsigned long bh_hash_mask = 0;
-static int grow_buffers(int pri, int size);
+static int grow_buffers(int size);
static struct buffer_head ** hash_table;
static struct buffer_head * lru_list[NR_LIST] = {NULL, };
*/
static void refill_freelist(int size)
{
- if (!grow_buffers(GFP_KERNEL, size)) {
+ if (!grow_buffers(size)) {
wakeup_bdflush(1);
current->policy |= SCHED_YIELD;
schedule();
* Try to increase the number of buffers available: the size argument
* is used to determine what kind of buffers we want.
*/
-static int grow_buffers(int pri, int size)
+static int grow_buffers(int size)
{
unsigned long page;
struct buffer_head *bh, *tmp;
return 0;
}
- if (!(page = __get_free_page(pri)))
+ if (!(page = __get_free_page(GFP_BUFFER)))
return 0;
bh = create_buffers(page, size, 0);
if (!bh) {
}
lru_list[BUF_CLEAN] = 0;
- grow_buffers(GFP_KERNEL, BLOCK_SIZE);
+ grow_buffers(BLOCK_SIZE);
}
int init_module(void)
{
int status;
- printk(KERN_INFO "Coda Kernel/Venus communications (module), v4.7.5, braam@cs.cmu.edu.\n");
+ printk(KERN_INFO "Coda Kernel/Venus communications (module), v5.0-pre1, braam@cs.cmu.edu.\n");
status = init_coda_psdev();
if ( status ) {
{
/* Handle invalidation requests. */
- if ( !sb ) {
+ if ( !sb || !sb->s_root || !sb->s_root->d_inode) {
printk("coda_downcall: opcode %d, no sb!\n", opcode);
return 0;
}
*/
int d_invalidate(struct dentry * dentry)
{
- /* Check whether to do a partial shrink_dcache */
+ /*
+ * Check whether to do a partial shrink_dcache
+ * to get rid of unused child entries.
+ */
if (!list_empty(&dentry->d_subdirs)) {
shrink_dcache_parent(dentry);
- if (!list_empty(&dentry->d_subdirs))
+ }
+
+ /*
+ * Somebody still using it?
+ *
+ * If it's a directory, we can't drop it
+ * for fear of somebody re-populating it
+ * with children (even though dropping it
+ * would make it unreachable from the root,
+ * we might still populate it if it was a
+ * working directory or similar).
+ */
+ if (dentry->d_count) {
+ if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
return -EBUSY;
}
* Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
if ((fs_type = get_fs_type("nfs"))) {
sb = get_empty_super(); /* "can't fail" */
sb->s_dev = get_unnamed_dev();
- sb->s_flags = root_mountflags & ~MS_RDONLY;
+ sb->s_flags = root_mountflags;
vfsmnt = add_vfsmnt(sb, "/dev/root", "/");
if (vfsmnt) {
if (nfs_root_mount(sb) >= 0) {
- sb->s_rd_only = 0;
sb->s_dirt = 0;
sb->s_type = fs_type;
current->fs->root = dget(sb->s_root);
current->fs->pwd = dget(sb->s_root);
ROOT_DEV = sb->s_dev;
- printk (KERN_NOTICE "VFS: Mounted root (nfs filesystem).\n");
+ printk (KERN_NOTICE "VFS: Mounted root (NFS filesystem)%s.\n", (sb->s_flags & MS_RDONLY) ? " readonly" : "");
return;
}
remove_vfsmnt(sb->s_dev);
brelse(bh);
return stored;
}
-#if 0 /* XXX */
- if (!ext2_check_dir_entry ("ext2_readdir", inode, de,
- /* XXX - beware about de having to be swabped somehow */
+ if (!ufs_check_dir_entry ("ufs_readdir", inode, de,
bh, offset)) {
/* On error, skip the f_pos to the
next block. */
brelse (bh);
return stored;
}
-#endif /* XXX */
offset += SWAB16(de->d_reclen);
if (de->d_ino) {
/* SWAB16() was unneeded -- compare to 0 */
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <stdarg.h>
ufs_set_opt (*mount_options, UFSTYPE_44BSD);
else if (!strcmp (value, "next"))
ufs_set_opt (*mount_options, UFSTYPE_NEXT);
+ else if (!strcmp (value, "openstep"))
+ ufs_set_opt (*mount_options, UFSTYPE_OPENSTEP);
else {
printk ("UFS-fs: Invalid type option: %s\n", value);
return 0;
}
if (!(sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE)) {
printk("You didn't specify type of your ufs file system\n\n"
- " mount -t ufs -o ufstype=sun|44bsd|old|next ....\n\n"
+ " mount -t ufs -o ufstype=sun|44bsd|old|next|openstep ....\n\n"
"!!! WARNING !!! wrong value may corrupt you file system\n"
"default value is ufstype=old\n");
ufs_set_opt (sb->u.ufs_sb.s_mount_opt, UFSTYPE_OLD);
flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD;
if (!(sb->s_flags & MS_RDONLY)) {
printk("old type of ufs is supported read-only\n");
- goto failed;
+ sb->s_flags |= MS_RDONLY;
}
break;
flags |= UFS_DE_OLD | UFS_UID_OLD | UFS_ST_OLD | UFS_CG_OLD;
if (!(sb->s_flags & MS_RDONLY)) {
printk("nextstep type of ufs is supported read-only\n");
- goto failed;
+ sb->s_flags |= MS_RDONLY;
}
break;
+ case UFS_MOUNT_UFSTYPE_OPENSTEP:
+ UFSD(("openstep ufstype\n"))
+ uspi->s_fsize = block_size = 1024;
+ uspi->s_fmask = ~(1024 - 1);
+ uspi->s_fshift = 10;
+ uspi->s_sbsize = super_block_size = 2048;
+ uspi->s_sbbase = 0;
+ flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
+ if (!(sb->s_flags & MS_RDONLY)) {
+ printk("openstep type of ufs is supported read-only\n");
+ sb->s_flags |= MS_RDONLY;
+ }
+ break;
default:
printk("this fs type of ufs is not supported\n");
}
#endif
- if ((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) ==
- UFS_MOUNT_UFSTYPE_NEXT && uspi->s_sbbase < 256) {
+ if ((((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) ==
+ UFS_MOUNT_UFSTYPE_NEXT) ||
+ ((sb->u.ufs_sb.s_mount_opt & UFS_MOUNT_UFSTYPE) ==
+ UFS_MOUNT_UFSTYPE_OPENSTEP)) && uspi->s_sbbase < 256) {
ubh_brelse_uspi(uspi);
ubh = NULL;
uspi->s_sbbase += 8;
/*
* The following structure is used to manage multiple PCI busses.
*
- * XXX: We should solve thos problem in an architecture independant
+ * XXX: We should solve this problem in an architecture independent
* way, rather than hacking something up here.
*/
#define B115200 00021
#define B230400 00022
#define B460800 00023
+#define B500000 00024
+#define B576000 00025
+#define B921600 00026
+#define B1000000 00027
+#define B1152000 00030
+#define B1500000 00031
+#define B2000000 00032
+#define B2500000 00033
+#define B3000000 00034
+#define B3500000 00035
+#define B4000000 00036
#define CSIZE 00001400
#define CS5 00000000
#define M_ARM 103
#include <asm/arch/a.out.h>
+
+#ifndef LIBRARY_START_TEXT
+#define LIBRARY_START_TEXT (0x00c00000)
+#endif
+
#endif /* __A_OUT_GNU_H__ */
#ifdef __KERNEL__
#define STACK_TOP (0x01a00000)
-#define LIBRARY_START_TEXT (0x00c00000)
#endif
#endif
#define MAX_DMA_ADDRESS 0x03000000
-/*
- * DMA modes - we have two, IN and OUT
- */
-typedef enum {
- DMA_MODE_READ,
- DMA_MODE_WRITE
-} dmamode_t;
-
#ifdef CONFIG_ARCH_ARC
#define MAX_DMA_CHANNELS 3
* source.
*/
#define HAS_IOC
+#include <asm/ioc.h>
#define HAS_MEMC
+#include <asm/memc.h>
#define HAS_MEMC1A
#define HAS_VIDC
"tst %2, #0x80000000\n\t"
"mov %0, %4\n\t"
"addeq %0, %0, %3\n\t"
- "strb %1, [%0, %2, lsl #2]"
+ "strb %1, [%0, %2, lsl #2] @ outb"
: "=&r" (temp)
: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
: "cc");
"tst %2, #0x80000000\n\t"
"mov %0, %4\n\t"
"addeq %0, %0, %3\n\t"
- "str %1, [%0, %2, lsl #2]"
+ "str %1, [%0, %2, lsl #2] @ outw"
: "=&r" (temp)
: "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
: "cc");
"tst %2, #0x80000000\n\t"
"mov %0, %4\n\t"
"addeq %0, %0, %3\n\t"
- "str %1, [%0, %2, lsl #2]"
+ "str %1, [%0, %2, lsl #2] @ outl"
: "=&r" (temp)
: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
: "cc");
"tst %2, #0x80000000\n\t" \
"mov %0, %4\n\t" \
"addeq %0, %0, %3\n\t" \
- "ldr" ##instr## " %1, [%0, %2, lsl #2]" \
+ "ldr" ##instr## " %1, [%0, %2, lsl #2] @ in"###fnsuffix \
: "=&r" (temp), "=r" (value) \
: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \
: "cc"); \
({ \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "strb %0, [%1, %2]" \
+ "strb %0, [%1, %2] @ outbc" \
: : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "strb %0, [%1, %2]" \
+ "strb %0, [%1, %2] @ outbc" \
: : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \
})
unsigned char result; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "ldrb %0, [%1, %2]" \
+ "ldrb %0, [%1, %2] @ inbc" \
: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "ldrb %0, [%1, %2]" \
+ "ldrb %0, [%1, %2] @ inbc" \
: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
result; \
})
unsigned long v = value; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "str %0, [%1, %2]" \
+ "str %0, [%1, %2] @ outwc" \
: : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "str %0, [%1, %2]" \
+ "str %0, [%1, %2] @ outwc" \
: : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2)); \
})
unsigned short result; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "ldr %0, [%1, %2]" \
+ "ldr %0, [%1, %2] @ inwc" \
: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "ldr %0, [%1, %2]" \
+ "ldr %0, [%1, %2] @ inwc" \
: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
result & 0xffff; \
})
unsigned long v = value; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "str %0, [%1, %2]" \
+ "str %0, [%1, %2] @ outlc" \
: : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "str %0, [%1, %2]" \
+ "str %0, [%1, %2] @ outlc" \
: : "r" (v), "r" (IO_BASE), "r" ((port) << 2)); \
})
unsigned long result; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "ldr %0, [%1, %2]" \
+ "ldr %0, [%1, %2] @ inlc" \
: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "ldr %0, [%1, %2]" \
+ "ldr %0, [%1, %2] @ inlc" \
: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
result; \
})
* space during mmap's.
*/
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr)
#define INIT_MMAP \
{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
#endif
-extern __inline__ void arch_hard_reset (void)
+extern __inline__ void arch_reset(char mode)
{
- extern void ecard_reset (int card);
+ extern void ecard_reset(int card);
+
+ /*
+ * Do any cleanups that the processor may require
+ */
+ processor._proc_fin();
/*
* Reset all expansion cards.
*/
- ecard_reset (-1);
+ ecard_reset(-1);
/*
* copy branch instruction to reset location and call it
*/
*(unsigned long *)0 = *(unsigned long *)0x03800000;
((void(*)(void))0)();
-
- /*
- * If that didn't work, loop endlessly
- */
- while (1);
}
#endif
#ifdef __KERNEL__
#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#define LIBRARY_START_TEXT (0x00c00000)
#endif
#endif
* bytes of RAM.
*/
#define MAX_DMA_ADDRESS 0xd0000000
-
-/*
- * DMA modes - we have two, IN and OUT
- */
-typedef enum {
- DMA_MODE_READ,
- DMA_MODE_WRITE
-} dmamode_t;
-
#define MAX_DMA_CHANNELS 8
#endif /* _ASM_ARCH_DMA_H */
#define MAPTOPHYS(a) ((unsigned long)(a) - PAGE_OFFSET)
#define KERNTOPHYS(a) ((unsigned long)(&a))
#define KERNEL_BASE (0xc0008000)
-#define SAFE_ADDR 0x40000000
+#define FLUSH_BASE_PHYS 0x40000000
#else
"tst %2, #0x80000000\n\t" \
"mov %0, %4\n\t" \
"addeq %0, %0, %3\n\t" \
- "str" ##instr## " %1, [%0, %2, lsl #2]" \
+ "str" ##instr## " %1, [%0, %2, lsl #2] @ out"###fnsuffix \
: "=&r" (temp) \
: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \
: "cc"); \
"tst %2, #0x80000000\n\t" \
"mov %0, %4\n\t" \
"addeq %0, %0, %3\n\t" \
- "ldr" ##instr## " %1, [%0, %2, lsl #2]" \
+ "ldr" ##instr## " %1, [%0, %2, lsl #2] @ in"###fnsuffix \
: "=&r" (temp), "=r" (value) \
: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \
: "cc"); \
({ \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "strb %0, [%1, %2]" \
+ "strb %0, [%1, %2] @ outbc" \
: : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "strb %0, [%1, %2]" \
+ "strb %0, [%1, %2] @ outbc" \
: : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \
})
unsigned char result; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "ldrb %0, [%1, %2]" \
+ "ldrb %0, [%1, %2] @ inbc" \
: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "ldrb %0, [%1, %2]" \
+ "ldrb %0, [%1, %2] @ inbc" \
: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
result; \
})
unsigned long v = value; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "str %0, [%1, %2]" \
+ "str %0, [%1, %2] @ outwc" \
: : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "str %0, [%1, %2]" \
+ "str %0, [%1, %2] @ outwc" \
: : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2)); \
})
unsigned short result; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "ldr %0, [%1, %2]" \
+ "ldr %0, [%1, %2] @ inwc" \
: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "ldr %0, [%1, %2]" \
+ "ldr %0, [%1, %2] @ inwc" \
: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
result & 0xffff; \
})
unsigned long v = value; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "str %0, [%1, %2]" \
+ "str %0, [%1, %2] @ outlc" \
: : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "str %0, [%1, %2]" \
+ "str %0, [%1, %2] @ outlc" \
: : "r" (v), "r" (IO_BASE), "r" ((port) << 2)); \
})
unsigned long result; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "ldr %0, [%1, %2]" \
+ "ldr %0, [%1, %2] @ inlc" \
: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "ldr %0, [%1, %2]" \
+ "ldr %0, [%1, %2] @ inlc" \
: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
result; \
})
* space during mmap's.
*/
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr)
#define INIT_MMAP \
{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
-extern __inline__ void arch_hard_reset (void)
+extern __inline__ void arch_reset(char mode)
{
/*
* loop endlessly
*/
cli();
- while (1);
}
#endif
* 10-Oct-1996 RMK Created
* 04-Dec-1997 RMK Updated for new arch/arm/kernel/time.c
* 07-Aug-1998 RMK Updated for arch/arm/kernel/leds.c
+ * 28-Dec-1998 APH Made leds code optional
*/
+#include <linux/config.h>
#include <asm/leds.h>
#define IRQ_TIMER IRQ_EBSA110_TIMER0
extern __inline__ int reset_timer (void)
{
static unsigned int divisor;
+#ifdef CONFIG_LEDS
static int count = 50;
+#endif
*PIT_T1 = (PIT1_COUNT) & 0xff;
*PIT_T1 = (PIT1_COUNT) >> 8;
+#ifdef CONFIG_LEDS
if (--count == 0) {
count = 50;
leds_event(led_timer);
}
+#endif
if (divisor == 0) {
divisor = DIVISOR - 1;
#ifdef __KERNEL__
#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#define LIBRARY_START_TEXT (0x00c00000)
#endif
#endif
*/
#define MAX_DMA_ADDRESS 0xffffffff
-/*
- * DMA modes - we have two, IN and OUT
- */
-
-typedef int dmamode_t;
-#define DMA_MODE_READ 0x44
-#define DMA_MODE_WRITE 0x48
-
/*
* The 21285 has two internal DMA channels; we call these 0 and 1.
* On CATS hardware we have an additional eight ISA dma channels
* numbered 2..9.
*/
#define MAX_DMA_CHANNELS 10
-
#define DMA_ISA_BASE 2
#define DMA_FLOPPY (DMA_ISA_BASE + 2)
* 0xf8000000 0x7b010000 PCI Config type 0
*
*/
+
+#include <asm/dec21285.h>
#define IO_BASE 0xe0000000
#define PCIO_BASE 0xffe00000
-
+#define PCI_IACK 0xfc000000
#define XBUS_LEDS ((volatile unsigned char *)0xfff12000)
#define XBUS_LED_AMBER (1 << 0)
#define XBUS_SWITCH_J17_11 ((*XBUS_SWITCH) & (1 << 5))
#define XBUS_SWITCH_J17_9 ((*XBUS_SWITCH) & (1 << 6))
-#define CSR_SA110_CNTL ((volatile unsigned long *)0xfe00013c)
-#define CSR_PCIADDR_EXTN ((volatile unsigned long *)0xfe000140)
-#define CSR_PREFETCHMEMRANGE ((volatile unsigned long *)0xfe000144)
-#define CSR_XBUS_CYCLE ((volatile unsigned long *)0xfe000148)
-#define CSR_XBUS_IOSTROBE ((volatile unsigned long *)0xfe00014c)
-#define CSR_DOORBELL_PCI ((volatile unsigned long *)0xfe000150)
-#define CSR_DOORBELL_SA110 ((volatile unsigned long *)0xfe000154)
-
-
-#define CSR_UARTDR ((volatile unsigned long *)0xfe000160)
-#define CSR_RXSTAT ((volatile unsigned long *)0xfe000164)
-#define CSR_H_UBRLCR ((volatile unsigned long *)0xfe000168)
-#define CSR_M_UBRLCR ((volatile unsigned long *)0xfe00016c)
-#define CSR_L_UBRLCR ((volatile unsigned long *)0xfe000170)
-#define CSR_UARTCON ((volatile unsigned long *)0xfe000174)
-#define CSR_UARTFLG ((volatile unsigned long *)0xfe000178)
-
-#define CSR_IRQ_STATUS ((volatile unsigned long *)0xfe000180)
-#define CSR_IRQ_RAWSTATUS ((volatile unsigned long *)0xfe000184)
-#define CSR_IRQ_ENABLE ((volatile unsigned long *)0xfe000188)
-#define CSR_IRQ_DISABLE ((volatile unsigned long *)0xfe00018c)
-#define CSR_IRQ_SOFT ((volatile unsigned long *)0xfe000190)
-
-#define CSR_FIQ_STATUS ((volatile unsigned long *)0xfe000280)
-#define CSR_FIQ_RAWSTATUS ((volatile unsigned long *)0xfe000284)
-#define CSR_FIQ_ENABLE ((volatile unsigned long *)0xfe000288)
-#define CSR_FIQ_DISABLE ((volatile unsigned long *)0xfe00028c)
-#define CSR_FIQ_SOFT ((volatile unsigned long *)0xfe000290)
-
-#define CSR_TIMER1_LOAD ((volatile unsigned long *)0xfe000300)
-#define CSR_TIMER1_VALUE ((volatile unsigned long *)0xfe000304)
-#define CSR_TIMER1_CNTL ((volatile unsigned long *)0xfe000308)
-#define CSR_TIMER1_CLR ((volatile unsigned long *)0xfe00030c)
-
-#define CSR_TIMER2_LOAD ((volatile unsigned long *)0xfe000320)
-#define CSR_TIMER2_VALUE ((volatile unsigned long *)0xfe000324)
-#define CSR_TIMER2_CNTL ((volatile unsigned long *)0xfe000328)
-#define CSR_TIMER2_CLR ((volatile unsigned long *)0xfe00032c)
-
-#define CSR_TIMER3_LOAD ((volatile unsigned long *)0xfe000340)
-#define CSR_TIMER3_VALUE ((volatile unsigned long *)0xfe000344)
-#define CSR_TIMER3_CNTL ((volatile unsigned long *)0xfe000348)
-#define CSR_TIMER3_CLR ((volatile unsigned long *)0xfe00034c)
-
-#define CSR_TIMER4_LOAD ((volatile unsigned long *)0xfe000360)
-#define CSR_TIMER4_VALUE ((volatile unsigned long *)0xfe000364)
-#define CSR_TIMER4_CNTL ((volatile unsigned long *)0xfe000368)
-#define CSR_TIMER4_CLR ((volatile unsigned long *)0xfe00036c)
-
-
-#define TIMER_CNTL_ENABLE (1 << 7)
-#define TIMER_CNTL_AUTORELOAD (1 << 6)
-#define TIMER_CNTL_DIV1 (0)
-#define TIMER_CNTL_DIV16 (1 << 2)
-#define TIMER_CNTL_DIV256 (2 << 2)
-#define TIMER_CNTL_CNTEXT (3 << 2)
-
-
#define KERNTOPHYS(a) ((unsigned long)(&a))
#define PARAMS_OFFSET 0x0100
#define PARAMS_BASE (PAGE_OFFSET + PARAMS_OFFSET)
-#define SAFE_ADDR 0x50000000
+#define FLUSH_BASE_PHYS 0x50000000
/*
- * linux/include/asm-arm/arch-ebsa110/io.h
+ * linux/include/asm-arm/arch-ebsa285/io.h
*
* Copyright (C) 1997,1998 Russell King
*
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
+#include <asm/dec21285.h>
+
/*
* This architecture does not require any delayed IO, and
* has the constant-optimised IO
extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port) \
{ \
__asm__ __volatile__( \
- "str" ##instr## " %0, [%1, %2]" \
+ "str%?" ##instr## " %0, [%1, %2] @ out"###fnsuffix \
: \
: "r" (value), "r" (PCIO_BASE), typ (port)); \
}
{ \
unsigned long value; \
__asm__ __volatile__( \
- "ldr" ##instr## " %0, [%1, %2]" \
+ "ldr%?" ##instr## " %0, [%1, %2] @ in"###fnsuffix \
: "=&r" (value) \
: "r" (PCIO_BASE), typ (port)); \
return (unsigned sz)value; \
#define __outbc(value,port) \
({ \
__asm__ __volatile__( \
- "strb %0, [%1, %2]" \
+ "str%?b %0, [%1, %2] @ outbc" \
: \
: "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
})
({ \
unsigned char result; \
__asm__ __volatile__( \
- "ldrb %0, [%1, %2]" \
+ "ldr%?b %0, [%1, %2] @ inbc" \
: "=r" (result) \
: "r" (PCIO_BASE), "Jr" (port)); \
result; \
#define __outwc(value,port) \
({ \
__asm__ __volatile__( \
- "strh %0, [%1, %2]" \
+ "str%?h %0, [%1, %2] @ outwc" \
: \
: "r" (value), "r" (PCIO_BASE), "r" (port)); \
})
({ \
unsigned short result; \
__asm__ __volatile__( \
- "ldrh %0, [%1, %2]" \
+ "ldr%?h %0, [%1, %2] @ inwc" \
: "=r" (result) \
: "r" (PCIO_BASE), "r" (port)); \
result & 0xffff; \
#define __outlc(value,port) \
({ \
__asm__ __volatile__( \
- "str %0, [%1, %2]" \
+ "str%? %0, [%1, %2] @ outlc" \
: \
: "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
})
({ \
unsigned long result; \
__asm__ __volatile__( \
- "ldr %0, [%1, %2]" \
+ "ldr%? %0, [%1, %2] @ inlc" \
: "=r" (result) \
: "r" (PCIO_BASE), "Jr" (port)); \
result; \
(*(volatile unsigned long *)(p))
/*
- * This is not sufficient... (and it's a hack anyway)
+ * ioremap support
+ */
+#define valid_ioaddr(iomem,size) ((iomem) < 0x80000000 && (iomem) + (size) <= 0x80000000)
+#define io_to_phys(iomem) ((iomem) + DC21285_PCI_MEM)
+
+/*
+ * Fudge up IO addresses by this much. Once we're confident that nobody
+ * is using read*() and so on with addresses they didn't get from ioremap
+ * this can go away.
+ */
+#define IO_FUDGE_FACTOR 0xe0000000
+
+extern inline void *ioremap(unsigned long iomem_addr, unsigned long size)
+{
+ unsigned long phys_addr;
+
+ if (!valid_ioaddr(iomem_addr, size))
+ return NULL;
+
+ phys_addr = io_to_phys(iomem_addr & PAGE_MASK);
+
+ return (void *)((unsigned long)__ioremap(phys_addr, size, 0)
+ - IO_FUDGE_FACTOR);
+}
+
+#define ioremap_nocache(iomem_addr,size) ioremap((iomem_addr),(size))
+
+extern void iounmap(void *addr);
+
+/*
+ * We'd probably be better off with these as macros rather than functions.
+ * Firstly that would be more efficient and secondly we could do with the
+ * ability to stop GCC whinging about type conversions. --philb
*/
static inline void writeb(unsigned char b, unsigned int addr)
{
- *(volatile unsigned char *)(0xe0000000 + (addr)) = b;
+ *(volatile unsigned char *)(IO_FUDGE_FACTOR + (addr)) = b;
}
static inline unsigned char readb(unsigned int addr)
{
- return *(volatile unsigned char *)(0xe0000000 + (addr));
+ return *(volatile unsigned char *)(IO_FUDGE_FACTOR + (addr));
}
static inline void writew(unsigned short b, unsigned int addr)
{
- *(volatile unsigned short *)(0xe0000000 + (addr)) = b;
+ *(volatile unsigned short *)(IO_FUDGE_FACTOR + (addr)) = b;
}
static inline unsigned short readw(unsigned int addr)
{
- return *(volatile unsigned short *)(0xe0000000 + (addr));
+ return *(volatile unsigned short *)(IO_FUDGE_FACTOR + (addr));
}
+
+static inline void writel(unsigned long b, unsigned int addr)
+{
+ *(volatile unsigned long *)(IO_FUDGE_FACTOR + (addr)) = b;
+}
+
+static inline unsigned short readl(unsigned int addr)
+{
+ return *(volatile unsigned long *)(IO_FUDGE_FACTOR + (addr));
+}
+
#endif
* 22-08-1998 RMK Restructured IRQ routines
* 03-09-1998 PJB Merged CATS support
*/
-
#include <linux/config.h>
static void ebsa285_mask_irq(unsigned int irq)
* On ebsa285, the dram is contiguous
*/
#define __virt_to_phys__is_a_macro
-#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET)
+#define __virt_to_phys(vpage) ((unsigned long)(vpage) - PAGE_OFFSET)
#define __phys_to_virt__is_a_macro
-#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
+#define __phys_to_virt(ppage) ((unsigned long)(ppage) + PAGE_OFFSET)
#define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x) (x - 0xe0000000)
+#define __virt_to_bus(x) ((x) - 0xe0000000)
#define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x) (x + 0xe0000000)
+#define __bus_to_virt(x) ((x) + 0xe0000000)
#endif
* space during mmap's.
*/
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr)
#define INIT_MMAP \
{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
#define __ASM_ARCH_SERIAL_H
#include <linux/config.h>
+
#include <asm/irq.h>
/*
#include <asm/hardware.h>
#include <asm/leds.h>
-/* To reboot, we set up the 21285 watchdog and enable it.
- * We then wait for it to timeout.
- */
-extern __inline__ void arch_hard_reset (void)
+extern __inline__ void arch_reset(char mode)
{
cli();
- *CSR_TIMER4_LOAD = 0x8000;
- *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
- *CSR_SA110_CNTL |= 1 << 13;
- while(1);
-}
-#define ARCH_IDLE_OK
+ if (mode == 's') {
+ __asm__ volatile (
+ "mov lr, #0x41000000 @ prepare to jump to ROM
+ mov r0, #0x130
+ mcr p15, 0, r0, c1, c0 @ MMU off
+ mcr p15, 0, ip, c7, c7 @ flush caches
+ mov pc, lr");
+ } else {
+ /* To reboot, we set up the 21285 watchdog and enable it.
+ * We then wait for it to timeout.
+ */
+ *CSR_TIMER4_LOAD = 0x8000;
+ *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
+ *CSR_SA110_CNTL |= 1 << 13;
+ }
+}
#define arch_start_idle() leds_event(led_idle_start)
#define arch_end_idle() leds_event(led_idle_end)
* Changelog:
* 21-Mar-1998 RMK Created
* 27-Aug-1998 PJB CATS support
+ * 28-Dec-1998 APH Made leds optional
*/
#define RTC_PORT(x) (0x72+(x))
#define RTC_ALWAYS_BCD 1
+#include <linux/config.h>
#include <asm/leds.h>
#include <asm/system.h>
#include <linux/mc146818rtc.h>
extern __inline__ unsigned long gettimeoffset (void)
{
- return 0;
+ unsigned long value = LATCH - *CSR_TIMER1_VALUE;
+
+ return (tick * value) / LATCH;
}
extern __inline__ int reset_timer (void)
{
*CSR_TIMER1_CLR = 0;
+#ifdef CONFIG_LEDS
/*
* Do the LEDs thing on EBSA-285 hardware.
*/
leds_event(led_timer);
}
}
-
+#endif
+
return 1;
}
* Copyright (C) 1996,1997,1998 Russell King
*/
+#define BASE 0x42000160
+
+static __inline__ void putc(char c)
+{
+ while (*((volatile unsigned int *)(BASE + 0x18)) & 8);
+ *((volatile unsigned int *)(BASE)) = c;
+}
+
/*
* This does not append a newline
*/
static void puts(const char *s)
{
- __asm__ __volatile__("
- ldrb %0, [%2], #1
- teq %0, #0
- beq 3f
-1: strb %0, [%3]
-2: ldrb %1, [%3, #0x14]
- and %1, %1, #0x60
- teq %1, #0x60
- bne 2b
- teq %0, #'\n'
- moveq %0, #'\r'
- beq 1b
- ldrb %0, [%2], #1
- teq %0, #0
- bne 1b
-3: " : : "r" (0), "r" (0), "r" (s), "r" (0xf0000be0) : "cc");
+ while (*s) {
+ putc(*s);
+ if (*s == '\n')
+ putc('\r');
+ s++;
+ }
}
/*
#ifdef __KERNEL__
#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#define LIBRARY_START_TEXT (0x00c00000)
#endif
#endif
* Copyright (C) 1998 Philip Blundell
*/
-/* Need this to keep <asm/dma.h> happy. */
-typedef unsigned int dmamode_t;
-
*/
#define RAM_BASE 0x40000000
#define KERNTOPHYS(a) ((unsigned long)(&a))
-#define SAFE_ADDR 0x40000000
+#define FLUSH_BASE_PHYS 0x40000000
#endif
* space during mmap's.
*/
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr)
#define INIT_MMAP \
{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
#ifndef __ASM_ARCH_SYSTEM_H
#define __ASM_ARCH_SYSTEM_H
-extern __inline__ void arch_hard_reset (void)
+extern __inline__ void arch_reset(char mode)
{
/*
* loop endlessly - the watchdog will reset us if it's enabled.
*/
cli();
- while (1);
}
#endif
#ifdef __KERNEL__
#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#define LIBRARY_START_TEXT (0x00c00000)
#endif
#endif
* bytes of RAM.
*/
#define MAX_DMA_ADDRESS 0xd0000000
-
-/*
- * DMA modes - we have two, IN and OUT
- */
-typedef enum {
- DMA_MODE_READ,
- DMA_MODE_WRITE
-} dmamode_t;
-
#define MAX_DMA_CHANNELS 8
#define DMA_0 0
* What hardware must be present
*/
#define HAS_IOMD
+#include <asm/iomd.h>
#define HAS_VIDC20
/* Hardware addresses of major areas.
"tst %2, #0x80000000\n\t" \
"mov %0, %4\n\t" \
"addeq %0, %0, %3\n\t" \
- "str" ##instr## " %1, [%0, %2, lsl #2]" \
+ "str" ##instr## " %1, [%0, %2, lsl #2] @ out"###fnsuffix \
: "=&r" (temp) \
: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \
: "cc"); \
"tst %2, #0x80000000\n\t" \
"mov %0, %4\n\t" \
"addeq %0, %0, %3\n\t" \
- "ldr" ##instr## " %1, [%0, %2, lsl #2]" \
+ "ldr" ##instr## " %1, [%0, %2, lsl #2] @ in"###fnsuffix \
: "=&r" (temp), "=r" (value) \
: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE) \
: "cc"); \
({ \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "strb %0, [%1, %2]" \
+ "strb %0, [%1, %2] @ outbc" \
: : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "strb %0, [%1, %2]" \
+ "strb %0, [%1, %2] @ outbc" \
: : "r" (value), "r" (IO_BASE), "r" ((port) << 2)); \
})
unsigned char result; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "ldrb %0, [%1, %2]" \
+ "ldrb %0, [%1, %2] @ inbc" \
: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "ldrb %0, [%1, %2]" \
+ "ldrb %0, [%1, %2] @ inbc" \
: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
result; \
})
unsigned long v = value; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "str %0, [%1, %2]" \
+ "str %0, [%1, %2] @ outwc" \
: : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "str %0, [%1, %2]" \
+ "str %0, [%1, %2] @ outwc" \
: : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2)); \
})
unsigned short result; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "ldr %0, [%1, %2]" \
+ "ldr %0, [%1, %2] @ inwc" \
: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "ldr %0, [%1, %2]" \
+ "ldr %0, [%1, %2] @ inwc" \
: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
result & 0xffff; \
})
unsigned long v = value; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "str %0, [%1, %2]" \
+ "str %0, [%1, %2] @ outlc" \
: : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "str %0, [%1, %2]" \
+ "str %0, [%1, %2] @ outlc" \
: : "r" (v), "r" (IO_BASE), "r" ((port) << 2)); \
})
unsigned long result; \
if (__PORT_PCIO((port))) \
__asm__ __volatile__( \
- "ldr %0, [%1, %2]" \
+ "ldr %0, [%1, %2] @ inlc" \
: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2)); \
else \
__asm__ __volatile__( \
- "ldr %0, [%1, %2]" \
+ "ldr %0, [%1, %2] @ inlc" \
: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2)); \
result; \
})
* space during mmap's.
*/
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr)
#define INIT_MMAP \
{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
#include <asm/proc-fns.h>
-#define arch_hard_reset() { \
+#define arch_reset(mode) { \
extern void ecard_reset (int card); \
outb (0, IOMD_ROMCR0); \
- ecard_reset (-1); \
+ ecard_reset(-1); \
cli(); \
__asm__ __volatile__("msr spsr, r1;" \
"mcr p15, 0, %0, c1, c0, 0;" \
#ifdef __KERNEL__
#define STACK_TOP ((current->personality==PER_LINUX_32BIT)? 0xc0000000 : 0x04000000)
-#define LIBRARY_START_TEXT (0x00c00000)
#endif
#endif
* bytes of RAM.
*/
#define MAX_DMA_ADDRESS 0xd0000000
-
-/*
- * DMA modes - we have two, IN and OUT
- */
-typedef enum {
- DMA_MODE_READ,
- DMA_MODE_WRITE
-} dmamode_t;
-
#define MAX_DMA_CHANNELS 8
#endif /* _ASM_ARCH_DMA_H */
//#define PARAMS_OFFSET 0x0100
//#define PARAMS_BASE (PAGE_OFFSET + PARAMS_OFFSET)
-#define SAFE_ADDR 0x50000000
+#define FLUSH_BASE_PHYS 0x50000000
+
+/* GPIO pins */
+#define GPIO_CCLK 0x800
+#define GPIO_DSCLK 0x400
+#define GPIO_E2CLK 0x200
+#define GPIO_IOLOAD 0x100
+#define GPIO_RED_LED 0x080
+#define GPIO_WDTIMER 0x040
+#define GPIO_DATA 0x020
+#define GPIO_IOCLK 0x010
+#define GPIO_DONE 0x008
+#define GPIO_FAN 0x004
+#define GPIO_GREEN_LED 0x002
+#define GPIO_RESET 0x001
+
+/* CPLD pins */
+#define CPLD_DSRESET 8
+#define CPLD_UNMUTE 2
+
+#ifndef __ASSEMBLY__
+extern void gpio_modify_op(int mask, int set);
+extern void gpio_modify_io(int mask, int in);
+extern int gpio_read(void);
+extern void cpld_modify(int mask, int set);
+#endif
extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port) \
{ \
__asm__ __volatile__( \
- "str" ##instr## " %0, [%1, %2]" \
+ "str%?" ##instr## " %0, [%1, %2] @ out"###fnsuffix \
: \
: "r" (value), "r" (PCIO_BASE), typ (port)); \
}
{ \
unsigned long value; \
__asm__ __volatile__( \
- "ldr" ##instr## " %0, [%1, %2]" \
+ "ldr%?" ##instr## " %0, [%1, %2] @ in"###fnsuffix \
: "=&r" (value) \
: "r" (PCIO_BASE), typ (port)); \
return (unsigned sz)value; \
#define __outbc(value,port) \
({ \
__asm__ __volatile__( \
- "strb %0, [%1, %2]" \
+ "strb %0, [%1, %2] @ outbc" \
: \
: "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
})
({ \
unsigned char result; \
__asm__ __volatile__( \
- "ldrb %0, [%1, %2]" \
+ "ldrb %0, [%1, %2] @ inbc" \
: "=r" (result) \
: "r" (PCIO_BASE), "Jr" (port)); \
result; \
#define __outwc(value,port) \
({ \
__asm__ __volatile__( \
- "strh %0, [%1, %2]" \
+ "strh %0, [%1, %2] @ outwc" \
: \
: "r" (value), "r" (PCIO_BASE), "r" (port)); \
})
({ \
unsigned short result; \
__asm__ __volatile__( \
- "ldrh %0, [%1, %2]" \
+ "ldrh %0, [%1, %2] @ inwc" \
: "=r" (result) \
: "r" (PCIO_BASE), "r" (port)); \
result & 0xffff; \
#define __outlc(value,port) \
({ \
__asm__ __volatile__( \
- "str %0, [%1, %2]" \
+ "str %0, [%1, %2] @ outlc" \
: \
: "r" (value), "r" (PCIO_BASE), "Jr" (port)); \
})
({ \
unsigned long result; \
__asm__ __volatile__( \
- "ldr %0, [%1, %2]" \
+ "ldr %0, [%1, %2] @ inlc" \
: "=r" (result) \
: "r" (PCIO_BASE), "Jr" (port)); \
result; \
#define IRQ_HARDDISK 30 /* from 553.14 */
/* These defines handle the translation from the above FB #defines
- * into physical buts for the FootBridge IRQ registers
+ * into physical bits for the FootBridge IRQ registers
*/
#define IRQ_MASK_SOFTIRQ 0x00000002
#define IRQ_MASK_UART_DEBUG 0x0000000C
#define IRQ_MASK_VIDCOMP 0x00000400
#define IRQ_MASK_EXTERN_IRQ 0x00000800
#define IRQ_MASK_DMA1 0x00030000
-#define IRQ_MASK_PCI_ERR 0xf0000000
+#define IRQ_MASK_PCI_ERR 0xf8800000
/*
* Now map them to the Linux interrupts
*/
+#undef IRQ_TIMER
#define IRQ_TIMER IRQ_TIMER0
+#undef RTC_IRQ
+#define RTC_IRQ IRQ_RTC_ALARM
+#undef AUX_IRQ
+#define AUX_IRQ IRQ_MOUSE
#define irq_cannonicalize(i) (i)
* space during mmap's.
*/
#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#define TASK_UNMAPPED_ALIGN(addr, off) PAGE_ALIGN(addr)
#define INIT_MMAP \
{ &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
/*
- * linux/include/asm-arm/arch-ebsa285/system.h
+ * linux/include/asm-arm/arch-vnc/system.h
*
* Copyright (c) 1996,1997,1998 Russell King.
* Copyright (c) 1998 Corel Computer Corp.
#include <asm/leds.h>
#include <asm/io.h>
-extern __inline__ void arch_hard_reset (void)
+extern __inline__ void arch_reset(char mode)
{
cli();
/* set a RED LED and toggle WD_TIMER for rebooting...
*/
outb(0xC4, 0x338);
-
- while(1);
}
-#define ARCH_IDLE_OK
-
#define arch_start_idle() leds_event(led_idle_start)
#define arch_end_idle() leds_event(led_idle_end)
* Copyright (c) 1997 Corel Computer Corp.
* Slight modifications to bring in line with ebsa285 port.
* -- Russell King.
+ * Added LED driver (based on the ebsa285 code) - Alex Holden 28/12/98.
*/
+#include <linux/config.h>
#include <linux/mc146818rtc.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
#undef IRQ_TIMER
#define IRQ_TIMER IRQ_TIMER4
+#define mSEC_10_from_14 ((14318180 + 100) / 200)
+
extern __inline__ unsigned long gettimeoffset (void)
{
- return 0;
+ int count;
+
+ static int count_p = (mSEC_10_from_14/6); /* for the first call after boot */
+ static unsigned long jiffies_p = 0;
+
+ /*
+ * cache volatile jiffies temporarily; we have IRQs turned off.
+ */
+ unsigned long jiffies_t;
+
+ /* timer count may underflow right here */
+ outb_p(0x00, 0x43); /* latch the count ASAP */
+
+ count = inb_p(0x40); /* read the latched count */
+
+ /*
+ * We do this guaranteed double memory access instead of a _p
+ * postfix in the previous port access. Wheee, hackady hack
+ */
+ jiffies_t = jiffies;
+
+ count |= inb_p(0x40) << 8;
+
+ /* Detect timer underflows. If we haven't had a timer tick since
+ the last time we were called, and time is apparently going
+ backwards, the counter must have wrapped during this routine. */
+ if ((jiffies_t == jiffies_p) && (count > count_p))
+ count -= (mSEC_10_from_14/6);
+ else
+ jiffies_p = jiffies_t;
+
+ count_p = count;
+
+ count = (((mSEC_10_from_14/6)-1) - count) * tick;
+ count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
+
+ return count;
}
extern __inline__ int reset_timer (void)
{
+#ifdef CONFIG_LEDS
+ static unsigned int count = 50;
+ static int last_pid;
+
+ if (current->pid != last_pid) {
+ last_pid = current->pid;
+ if (last_pid)
+ leds_event(led_idle_end);
+ else
+ leds_event(led_idle_start);
+ }
+
+ if (--count == 0) {
+ count = 50;
+ leds_event(led_timer);
+ }
+#endif
return 1;
}
return mktime(year, mon, day, hour, min, sec);
}
-#define mSEC_10_from_14 ((14318180 + 100) / 200)
-
/*
* Set up timer interrupt, and return the current time in seconds.
*/
#ifndef __ASM_ARM_ATOMIC_H
#define __ASM_ARM_ATOMIC_H
+#ifdef __SMP__
+#error SMP not supported
+#endif
+
+#include <linux/config.h>
+
+#ifdef CONFIG_ARCH_CO285
+typedef struct { volatile int counter; } atomic_t;
+#else
typedef struct { int counter; } atomic_t;
+#endif
#define ATOMIC_INIT(i) { (i) }
#ifdef __KERNEL__
#include <asm/system.h>
-#ifdef __SMP__
-#error SMP not supported
-#endif
-
#define atomic_read(v) ((v)->counter)
#define atomic_set(v,i) (((v)->counter) = (i))
#include <asm/types.h>
-#if defined(__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ < 80
+#if defined(__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ < 8
-/* Recent versions of GCC can do as well or better than this
- on their own - we shouldn't interfere. */
+/* Recent versions of GCC can open code the swaps at least as well
+ as we can write them by hand, so the "optimisations" here only
+ make sense for older compilers. Worse, some versions of GCC
+ actually go wrong in the presence of the assembler versions.
+ We play it safe and only turn them on for compilers older than
+ GCC 2.8.0. */
static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
{
#endif /* __GNUC__ */
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+# define __BYTEORDER_HAS_U64__
+# define __SWAB_64_THRU_32__
+#endif
+
#include <linux/byteorder/little_endian.h>
#endif
* include/asm-arm/dec21285.h
*
* Copyright (C) 1998 Russell King
+ *
+ * DC21285 registers
*/
#define DC21285_PCI_IACK 0x79000000
#define DC21285_ARMCSR_BASE 0x42000000
#define DC21285_PCI_MEM 0x80000000
#ifndef __ASSEMBLY__
-
-/*
- * DEC21285
- */
-#define CSR_SA110_CNTL ((volatile unsigned long *)0xfe00013c)
-#define CSR_PCIADDR_EXTN ((volatile unsigned long *)0xfe000140)
-#define CSR_PREFETCHMEMRANGE ((volatile unsigned long *)0xfe000144)
-#define CSR_XBUS_CYCLE ((volatile unsigned long *)0xfe000148)
-#define CSR_XBUS_IOSTROBE ((volatile unsigned long *)0xfe00014c)
-#define CSR_DOORBELL_PCI ((volatile unsigned long *)0xfe000150)
-#define CSR_DOORBELL_SA110 ((volatile unsigned long *)0xfe000154)
-
-#define CSR_UARTDR ((volatile unsigned long *)0xfe000160)
-#define CSR_RXSTAT ((volatile unsigned long *)0xfe000164)
-#define CSR_H_UBRLCR ((volatile unsigned long *)0xfe000168)
-#define CSR_M_UBRLCR ((volatile unsigned long *)0xfe00016c)
-#define CSR_L_UBRLCR ((volatile unsigned long *)0xfe000170)
-#define CSR_UARTCON ((volatile unsigned long *)0xfe000174)
-#define CSR_UARTFLG ((volatile unsigned long *)0xfe000178)
-
-#define CSR_IRQ_STATUS ((volatile unsigned long *)0xfe000180)
-#define CSR_IRQ_RAWSTATUS ((volatile unsigned long *)0xfe000184)
-#define CSR_IRQ_ENABLE ((volatile unsigned long *)0xfe000188)
-#define CSR_IRQ_DISABLE ((volatile unsigned long *)0xfe00018c)
-#define CSR_IRQ_SOFT ((volatile unsigned long *)0xfe000190)
-
-#define CSR_FIQ_STATUS ((volatile unsigned long *)0xfe000280)
-#define CSR_FIQ_RAWSTATUS ((volatile unsigned long *)0xfe000284)
-#define CSR_FIQ_ENABLE ((volatile unsigned long *)0xfe000288)
-#define CSR_FIQ_DISABLE ((volatile unsigned long *)0xfe00028c)
-#define CSR_FIQ_SOFT ((volatile unsigned long *)0xfe000290)
-
-#define CSR_TIMER1_LOAD ((volatile unsigned long *)0xfe000300)
-#define CSR_TIMER1_VALUE ((volatile unsigned long *)0xfe000304)
-#define CSR_TIMER1_CNTL ((volatile unsigned long *)0xfe000308)
-#define CSR_TIMER1_CLR ((volatile unsigned long *)0xfe00030c)
-
-#define CSR_TIMER2_LOAD ((volatile unsigned long *)0xfe000320)
-#define CSR_TIMER2_VALUE ((volatile unsigned long *)0xfe000324)
-#define CSR_TIMER2_CNTL ((volatile unsigned long *)0xfe000328)
-#define CSR_TIMER2_CLR ((volatile unsigned long *)0xfe00032c)
-
-#define CSR_TIMER3_LOAD ((volatile unsigned long *)0xfe000340)
-#define CSR_TIMER3_VALUE ((volatile unsigned long *)0xfe000344)
-#define CSR_TIMER3_CNTL ((volatile unsigned long *)0xfe000348)
-#define CSR_TIMER3_CLR ((volatile unsigned long *)0xfe00034c)
-
-#define CSR_TIMER4_LOAD ((volatile unsigned long *)0xfe000360)
-#define CSR_TIMER4_VALUE ((volatile unsigned long *)0xfe000364)
-#define CSR_TIMER4_CNTL ((volatile unsigned long *)0xfe000368)
-#define CSR_TIMER4_CLR ((volatile unsigned long *)0xfe00036c)
-
+#define DC21285_IO(x) ((volatile unsigned long *)(0xfe000000+(x)))
#else
-
-#define CSR_SA110_CNTL 0x13c
-#define CSR_PCIADDR_EXTN 0x140
-#define CSR_PREFETCHMEMRANGE 0x144
-#define CSR_XBUS_CYCLE 0x148
-#define CSR_XBUS_IOSTROBE 0x14c
-#define CSR_DOORBELL_PCI 0x150
-#define CSR_DOORBELL_SA110 0x154
-
-#define CSR_UARTDR 0x160
-#define CSR_RXSTAT 0x164
-#define CSR_H_UBRLCR 0x168
-#define CSR_M_UBRLCR 0x16c
-#define CSR_L_UBRLCR 0x170
-#define CSR_UARTCON 0x174
-#define CSR_UARTFLG 0x178
-
-#define CSR_IRQ_STATUS 0x180
-#define CSR_IRQ_RAWSTATUS 0x184
-#define CSR_IRQ_ENABLE 0x188
-#define CSR_IRQ_DISABLE 0x18c
-#define CSR_IRQ_SOFT 0x190
-
-#define CSR_FIQ_STATUS 0x280
-#define CSR_FIQ_RAWSTATUS 0x284
-#define CSR_FIQ_ENABLE 0x288
-#define CSR_FIQ_DISABLE 0x28c
-#define CSR_FIQ_SOFT 0x290
-
-#define CSR_TIMER1_LOAD 0x300
-#define CSR_TIMER1_VALUE 0x304
-#define CSR_TIMER1_CNTL 0x308
-#define CSR_TIMER1_CLR 0x30c
-
-#define CSR_TIMER2_LOAD 0x320
-#define CSR_TIMER2_VALUE 0x324
-#define CSR_TIMER2_CNTL 0x328
-#define CSR_TIMER2_CLR 0x32c
-
-#define CSR_TIMER3_LOAD 0x340
-#define CSR_TIMER3_VALUE 0x344
-#define CSR_TIMER3_CNTL 0x348
-#define CSR_TIMER3_CLR 0x34c
-
-#define CSR_TIMER4_LOAD 0x360
-#define CSR_TIMER4_VALUE 0x364
-#define CSR_TIMER4_CNTL 0x368
-#define CSR_TIMER4_CLR 0x36c
-
+#define DC21285_IO(x) (x)
#endif
+#define CSR_PCICMD DC21285_IO(0x0004)
+#define CSR_PCICACHELINESIZE DC21285_IO(0x000c)
+#define CSR_PCICSRBASE DC21285_IO(0x0010)
+#define CSR_PCICSRIOBASE DC21285_IO(0x0014)
+#define CSR_PCISDRAMBASE DC21285_IO(0x0018)
+#define CSR_PCIROMBASE DC21285_IO(0x0030)
+#define CSR_CSRBASEMASK DC21285_IO(0x00f8)
+#define CSR_CSRBASEOFFSET DC21285_IO(0x00fc)
+#define CSR_SDRAMBASEMASK DC21285_IO(0x0100)
+#define CSR_SDRAMBASEOFFSET DC21285_IO(0x0104)
+#define CSR_ROMBASEMASK DC21285_IO(0x0108)
+#define CSR_SDRAMTIMING DC21285_IO(0x010c)
+#define CSR_SDRAMADDRSIZE0 DC21285_IO(0x0110)
+#define CSR_SDRAMADDRSIZE1 DC21285_IO(0x0114)
+#define CSR_SDRAMADDRSIZE2 DC21285_IO(0x0118)
+#define CSR_SDRAMADDRSIZE3 DC21285_IO(0x011c)
+#define CSR_I2O_INFREEHEAD DC21285_IO(0x0120)
+#define CSR_I2O_INPOSTTAIL DC21285_IO(0x0124)
+#define CSR_I2O_OUTPOSTHEAD DC21285_IO(0x0128)
+#define CSR_I2O_OUTFREETAIL DC21285_IO(0x012c)
+#define CSR_I2O_INFREECOUNT DC21285_IO(0x0130)
+#define CSR_I2O_OUTPOSTCOUNT DC21285_IO(0x0134)
+#define CSR_I2O_INPOSTCOUNT DC21285_IO(0x0138)
+#define CSR_SA110_CNTL DC21285_IO(0x013c)
+#define CSR_PCIADDR_EXTN DC21285_IO(0x0140)
+#define CSR_PREFETCHMEMRANGE DC21285_IO(0x0144)
+#define CSR_XBUS_CYCLE DC21285_IO(0x0148)
+#define CSR_XBUS_IOSTROBE DC21285_IO(0x014c)
+#define CSR_DOORBELL_PCI DC21285_IO(0x0150)
+#define CSR_DOORBELL_SA110 DC21285_IO(0x0154)
+#define CSR_UARTDR DC21285_IO(0x0160)
+#define CSR_RXSTAT DC21285_IO(0x0164)
+#define CSR_H_UBRLCR DC21285_IO(0x0168)
+#define CSR_M_UBRLCR DC21285_IO(0x016c)
+#define CSR_L_UBRLCR DC21285_IO(0x0170)
+#define CSR_UARTCON DC21285_IO(0x0174)
+#define CSR_UARTFLG DC21285_IO(0x0178)
+#define CSR_IRQ_STATUS DC21285_IO(0x0180)
+#define CSR_IRQ_RAWSTATUS DC21285_IO(0x0184)
+#define CSR_IRQ_ENABLE DC21285_IO(0x0188)
+#define CSR_IRQ_DISABLE DC21285_IO(0x018c)
+#define CSR_IRQ_SOFT DC21285_IO(0x0190)
+#define CSR_FIQ_STATUS DC21285_IO(0x0280)
+#define CSR_FIQ_RAWSTATUS DC21285_IO(0x0284)
+#define CSR_FIQ_ENABLE DC21285_IO(0x0288)
+#define CSR_FIQ_DISABLE DC21285_IO(0x028c)
+#define CSR_FIQ_SOFT DC21285_IO(0x0290)
+#define CSR_TIMER1_LOAD DC21285_IO(0x0300)
+#define CSR_TIMER1_VALUE DC21285_IO(0x0304)
+#define CSR_TIMER1_CNTL DC21285_IO(0x0308)
+#define CSR_TIMER1_CLR DC21285_IO(0x030c)
+#define CSR_TIMER2_LOAD DC21285_IO(0x0320)
+#define CSR_TIMER2_VALUE DC21285_IO(0x0324)
+#define CSR_TIMER2_CNTL DC21285_IO(0x0328)
+#define CSR_TIMER2_CLR DC21285_IO(0x032c)
+#define CSR_TIMER3_LOAD DC21285_IO(0x0340)
+#define CSR_TIMER3_VALUE DC21285_IO(0x0344)
+#define CSR_TIMER3_CNTL DC21285_IO(0x0348)
+#define CSR_TIMER3_CLR DC21285_IO(0x034c)
+#define CSR_TIMER4_LOAD DC21285_IO(0x0360)
+#define CSR_TIMER4_VALUE DC21285_IO(0x0364)
+#define CSR_TIMER4_CNTL DC21285_IO(0x0368)
+#define CSR_TIMER4_CLR DC21285_IO(0x036c)
+
#define TIMER_CNTL_ENABLE (1 << 7)
#define TIMER_CNTL_AUTORELOAD (1 << 6)
#define TIMER_CNTL_DIV1 (0)
typedef unsigned int dmach_t;
+#include <linux/config.h>
+#include <linux/kernel.h>
#include <asm/irq.h>
+#include <asm/system.h>
#include <asm/spinlock.h>
#include <asm/arch/dma.h>
+/*
+ * DMA modes - we have two, IN and OUT
+ */
+typedef unsigned int dmamode_t;
+
+#define DMA_MODE_MASK 1
+
+#define DMA_MODE_READ 0
+#define DMA_MODE_WRITE 1
+#define DMA_AUTOINIT 2
+
typedef struct {
unsigned long address;
unsigned long length;
#define NO_DMA 255
#endif
+#ifdef CONFIG_PCI_QUIRKS
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy (0)
+#endif
+
#endif /* _ARM_DMA_H */
#include <asm/arch/hardware.h>
-/*
- * Use these macros to read/write the IOC. All it does is perform the actual
- * read/write.
- */
-#ifdef HAS_IOC
-#ifndef __ASSEMBLER__
-#define __IOC(offset) (IOC_BASE + (offset >> 2))
-#else
-#define __IOC(offset) offset
-#endif
-
-#define IOC_CONTROL __IOC(0x00)
-#define IOC_KARTTX __IOC(0x04)
-#define IOC_KARTRX __IOC(0x04)
-
-#define IOC_IRQSTATA __IOC(0x10)
-#define IOC_IRQREQA __IOC(0x14)
-#define IOC_IRQCLRA __IOC(0x14)
-#define IOC_IRQMASKA __IOC(0x18)
-
-#define IOC_IRQSTATB __IOC(0x20)
-#define IOC_IRQREQB __IOC(0x24)
-#define IOC_IRQMASKB __IOC(0x28)
-
-#define IOC_FIQSTAT __IOC(0x30)
-#define IOC_FIQREQ __IOC(0x34)
-#define IOC_FIQMASK __IOC(0x38)
-
-#define IOC_T0CNTL __IOC(0x40)
-#define IOC_T0LTCHL __IOC(0x40)
-#define IOC_T0CNTH __IOC(0x44)
-#define IOC_T0LTCHH __IOC(0x44)
-#define IOC_T0GO __IOC(0x48)
-#define IOC_T0LATCH __IOC(0x4c)
-
-#define IOC_T1CNTL __IOC(0x50)
-#define IOC_T1LTCHL __IOC(0x50)
-#define IOC_T1CNTH __IOC(0x54)
-#define IOC_T1LTCHH __IOC(0x54)
-#define IOC_T1GO __IOC(0x58)
-#define IOC_T1LATCH __IOC(0x5c)
-
-#define IOC_T2CNTL __IOC(0x60)
-#define IOC_T2LTCHL __IOC(0x60)
-#define IOC_T2CNTH __IOC(0x64)
-#define IOC_T2LTCHH __IOC(0x64)
-#define IOC_T2GO __IOC(0x68)
-#define IOC_T2LATCH __IOC(0x6c)
-
-#define IOC_T3CNTL __IOC(0x70)
-#define IOC_T3LTCHL __IOC(0x70)
-#define IOC_T3CNTH __IOC(0x74)
-#define IOC_T3LTCHH __IOC(0x74)
-#define IOC_T3GO __IOC(0x78)
-#define IOC_T3LATCH __IOC(0x7c)
-#endif
-
-#ifdef HAS_MEMC
-#define VDMA_ALIGNMENT PAGE_SIZE
-#define VDMA_XFERSIZE 16
-#define VDMA_INIT 0
-#define VDMA_START 1
-#define VDMA_END 2
-
-#define video_set_dma(start,end,offset) \
-do { \
- memc_write (VDMA_START, (start >> 2)); \
- memc_write (VDMA_END, (end - VDMA_XFERSIZE) >> 2); \
- memc_write (VDMA_INIT, (offset >> 2)); \
-} while (0)
-#endif
-
-#ifdef HAS_IOMD
-#ifndef __ASSEMBLER__
-#define __IOMD(offset) (IO_IOMD_BASE + (offset >> 2))
-#else
-#define __IOMD(offset) offset
-#endif
-
-#define IOMD_CONTROL __IOMD(0x000)
-#define IOMD_KARTTX __IOMD(0x004)
-#define IOMD_KARTRX __IOMD(0x004)
-#define IOMD_KCTRL __IOMD(0x008)
-
-#define IOMD_IRQSTATA __IOMD(0x010)
-#define IOMD_IRQREQA __IOMD(0x014)
-#define IOMD_IRQCLRA __IOMD(0x014)
-#define IOMD_IRQMASKA __IOMD(0x018)
-
-#define IOMD_IRQSTATB __IOMD(0x020)
-#define IOMD_IRQREQB __IOMD(0x024)
-#define IOMD_IRQMASKB __IOMD(0x028)
-
-#define IOMD_FIQSTAT __IOMD(0x030)
-#define IOMD_FIQREQ __IOMD(0x034)
-#define IOMD_FIQMASK __IOMD(0x038)
-
-#define IOMD_T0CNTL __IOMD(0x040)
-#define IOMD_T0LTCHL __IOMD(0x040)
-#define IOMD_T0CNTH __IOMD(0x044)
-#define IOMD_T0LTCHH __IOMD(0x044)
-#define IOMD_T0GO __IOMD(0x048)
-#define IOMD_T0LATCH __IOMD(0x04c)
-
-#define IOMD_T1CNTL __IOMD(0x050)
-#define IOMD_T1LTCHL __IOMD(0x050)
-#define IOMD_T1CNTH __IOMD(0x054)
-#define IOMD_T1LTCHH __IOMD(0x054)
-#define IOMD_T1GO __IOMD(0x058)
-#define IOMD_T1LATCH __IOMD(0x05c)
-
-#define IOMD_ROMCR0 __IOMD(0x080)
-#define IOMD_ROMCR1 __IOMD(0x084)
-#define IOMD_DRAMCR __IOMD(0x088)
-#define IOMD_VREFCR __IOMD(0x08C)
-
-#define IOMD_FSIZE __IOMD(0x090)
-#define IOMD_ID0 __IOMD(0x094)
-#define IOMD_ID1 __IOMD(0x098)
-#define IOMD_VERSION __IOMD(0x09C)
-
-#define IOMD_MOUSEX __IOMD(0x0A0)
-#define IOMD_MOUSEY __IOMD(0x0A4)
-
-#define IOMD_DMATCR __IOMD(0x0C0)
-#define IOMD_IOTCR __IOMD(0x0C4)
-#define IOMD_ECTCR __IOMD(0x0C8)
-#define IOMD_DMAEXT __IOMD(0x0CC)
-
-#define DMA_EXT_IO0 1
-#define DMA_EXT_IO1 2
-#define DMA_EXT_IO2 4
-#define DMA_EXT_IO3 8
-
-#define IOMD_IO0CURA __IOMD(0x100)
-#define IOMD_IO0ENDA __IOMD(0x104)
-#define IOMD_IO0CURB __IOMD(0x108)
-#define IOMD_IO0ENDB __IOMD(0x10C)
-#define IOMD_IO0CR __IOMD(0x110)
-#define IOMD_IO0ST __IOMD(0x114)
-
-#define IOMD_IO1CURA __IOMD(0x120)
-#define IOMD_IO1ENDA __IOMD(0x124)
-#define IOMD_IO1CURB __IOMD(0x128)
-#define IOMD_IO1ENDB __IOMD(0x12C)
-#define IOMD_IO1CR __IOMD(0x130)
-#define IOMD_IO1ST __IOMD(0x134)
-
-#define IOMD_IO2CURA __IOMD(0x140)
-#define IOMD_IO2ENDA __IOMD(0x144)
-#define IOMD_IO2CURB __IOMD(0x148)
-#define IOMD_IO2ENDB __IOMD(0x14C)
-#define IOMD_IO2CR __IOMD(0x150)
-#define IOMD_IO2ST __IOMD(0x154)
-
-#define IOMD_IO3CURA __IOMD(0x160)
-#define IOMD_IO3ENDA __IOMD(0x164)
-#define IOMD_IO3CURB __IOMD(0x168)
-#define IOMD_IO3ENDB __IOMD(0x16C)
-#define IOMD_IO3CR __IOMD(0x170)
-#define IOMD_IO3ST __IOMD(0x174)
-
-#define IOMD_SD0CURA __IOMD(0x180)
-#define IOMD_SD0ENDA __IOMD(0x184)
-#define IOMD_SD0CURB __IOMD(0x188)
-#define IOMD_SD0ENDB __IOMD(0x18C)
-#define IOMD_SD0CR __IOMD(0x190)
-#define IOMD_SD0ST __IOMD(0x194)
-
-#define IOMD_SD1CURA __IOMD(0x1A0)
-#define IOMD_SD1ENDA __IOMD(0x1A4)
-#define IOMD_SD1CURB __IOMD(0x1A8)
-#define IOMD_SD1ENDB __IOMD(0x1AC)
-#define IOMD_SD1CR __IOMD(0x1B0)
-#define IOMD_SD1ST __IOMD(0x1B4)
-
-#define IOMD_CURSCUR __IOMD(0x1C0)
-#define IOMD_CURSINIT __IOMD(0x1C4)
-
-#define IOMD_VIDCUR __IOMD(0x1D0)
-#define IOMD_VIDEND __IOMD(0x1D4)
-#define IOMD_VIDSTART __IOMD(0x1D8)
-#define IOMD_VIDINIT __IOMD(0x1DC)
-#define IOMD_VIDCR __IOMD(0x1E0)
-
-#define IOMD_DMASTAT __IOMD(0x1F0)
-#define IOMD_DMAREQ __IOMD(0x1F4)
-#define IOMD_DMAMASK __IOMD(0x1F8)
-
-#define DMA_END_S (1 << 31)
-#define DMA_END_L (1 << 30)
-
-#define DMA_CR_C 0x80
-#define DMA_CR_D 0x40
-#define DMA_CR_E 0x20
-
-#define DMA_ST_OFL 4
-#define DMA_ST_INT 2
-#define DMA_ST_AB 1
-/*
- * IOC compatability
- */
-#define IOC_CONTROL IOMD_CONTROL
-#define IOC_IRQSTATA IOMD_IRQSTATA
-#define IOC_IRQREQA IOMD_IRQREQA
-#define IOC_IRQCLRA IOMD_IRQCLRA
-#define IOC_IRQMASKA IOMD_IRQMASKA
-
-#define IOC_IRQSTATB IOMD_IRQSTATB
-#define IOC_IRQREQB IOMD_IRQREQB
-#define IOC_IRQMASKB IOMD_IRQMASKB
-
-#define IOC_FIQSTAT IOMD_FIQSTAT
-#define IOC_FIQREQ IOMD_FIQREQ
-#define IOC_FIQMASK IOMD_FIQMASK
-
-#define IOC_T0CNTL IOMD_T0CNTL
-#define IOC_T0LTCHL IOMD_T0LTCHL
-#define IOC_T0CNTH IOMD_T0CNTH
-#define IOC_T0LTCHH IOMD_T0LTCHH
-#define IOC_T0GO IOMD_T0GO
-#define IOC_T0LATCH IOMD_T0LATCH
-
-#define IOC_T1CNTL IOMD_T1CNTL
-#define IOC_T1LTCHL IOMD_T1LTCHL
-#define IOC_T1CNTH IOMD_T1CNTH
-#define IOC_T1LTCHH IOMD_T1LTCHH
-#define IOC_T1GO IOMD_T1GO
-#define IOC_T1LATCH IOMD_T1LATCH
-
-/*
- * DMA (MEMC) compatability
- */
-#define HALF_SAM vram_half_sam
-#define VDMA_ALIGNMENT (HALF_SAM * 2)
-#define VDMA_XFERSIZE (HALF_SAM)
-#define VDMA_INIT IOMD_VIDINIT
-#define VDMA_START IOMD_VIDSTART
-#define VDMA_END IOMD_VIDEND
-
-#ifndef __ASSEMBLER__
-extern unsigned int vram_half_sam;
-#define video_set_dma(start,end,offset) \
-do { \
- outl (SCREEN_START + start, VDMA_START); \
- outl (SCREEN_START + end - VDMA_XFERSIZE, VDMA_END); \
- if (offset >= end - VDMA_XFERSIZE) \
- offset |= 0x40000000; \
- outl (SCREEN_START + offset, VDMA_INIT); \
-} while (0)
-#endif
+#ifndef FLUSH_BASE
+#define FLUSH_BASE 0xdf000000
#endif
#ifdef HAS_EXPMASK
/* C routines */
-#ifdef CONFIG_BINUTILS_NEW
+#ifdef CONFIG_TEXT_INIT_SECTION
#define __init __attribute__ ((__section__ (".text.init")))
#define __initfunc(__arginit) \
#define __INITDATA .section ".data.init",@alloc,@write
#define __FINIT .previous
+#define __cacheline_aligned __attribute__ \
+ ((__aligned__ (L1_CACHE_BYTES)))
+
#endif
* to an address that the kernel can use.
*/
#define virt_to_bus(x) (__virt_to_bus((unsigned long)(x)))
-#define bus_to_virt(x) ((void *)(__bus_to_virt(x)))
+#define bus_to_virt(x) ((void *)(__bus_to_virt((unsigned long)(x))))
/*
* These macros actually build the multi-value IO function prototypes
#ifdef __KERNEL__
+extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+
/*
* String version of IO memory access ops:
*/
--- /dev/null
+/*
+ * Use these macros to read/write the IOC. All it does is perform the actual
+ * read/write.
+ */
+
+#ifndef __ASSEMBLER__
+#define __IOC(offset) (IOC_BASE + (offset >> 2))
+#else
+#define __IOC(offset) offset
+#endif
+
+#define IOC_CONTROL __IOC(0x00)
+#define IOC_KARTTX __IOC(0x04)
+#define IOC_KARTRX __IOC(0x04)
+
+#define IOC_IRQSTATA __IOC(0x10)
+#define IOC_IRQREQA __IOC(0x14)
+#define IOC_IRQCLRA __IOC(0x14)
+#define IOC_IRQMASKA __IOC(0x18)
+
+#define IOC_IRQSTATB __IOC(0x20)
+#define IOC_IRQREQB __IOC(0x24)
+#define IOC_IRQMASKB __IOC(0x28)
+
+#define IOC_FIQSTAT __IOC(0x30)
+#define IOC_FIQREQ __IOC(0x34)
+#define IOC_FIQMASK __IOC(0x38)
+
+#define IOC_T0CNTL __IOC(0x40)
+#define IOC_T0LTCHL __IOC(0x40)
+#define IOC_T0CNTH __IOC(0x44)
+#define IOC_T0LTCHH __IOC(0x44)
+#define IOC_T0GO __IOC(0x48)
+#define IOC_T0LATCH __IOC(0x4c)
+
+#define IOC_T1CNTL __IOC(0x50)
+#define IOC_T1LTCHL __IOC(0x50)
+#define IOC_T1CNTH __IOC(0x54)
+#define IOC_T1LTCHH __IOC(0x54)
+#define IOC_T1GO __IOC(0x58)
+#define IOC_T1LATCH __IOC(0x5c)
+
+#define IOC_T2CNTL __IOC(0x60)
+#define IOC_T2LTCHL __IOC(0x60)
+#define IOC_T2CNTH __IOC(0x64)
+#define IOC_T2LTCHH __IOC(0x64)
+#define IOC_T2GO __IOC(0x68)
+#define IOC_T2LATCH __IOC(0x6c)
+
+#define IOC_T3CNTL __IOC(0x70)
+#define IOC_T3LTCHL __IOC(0x70)
+#define IOC_T3CNTH __IOC(0x74)
+#define IOC_T3LTCHH __IOC(0x74)
+#define IOC_T3GO __IOC(0x78)
+#define IOC_T3LATCH __IOC(0x7c)
+
--- /dev/null
+
+#ifndef __ASSEMBLER__
+#define __IOMD(offset) (IO_IOMD_BASE + (offset >> 2))
+#else
+#define __IOMD(offset) offset
+#endif
+
+#define IOMD_CONTROL __IOMD(0x000)
+#define IOMD_KARTTX __IOMD(0x004)
+#define IOMD_KARTRX __IOMD(0x004)
+#define IOMD_KCTRL __IOMD(0x008)
+
+#define IOMD_IRQSTATA __IOMD(0x010)
+#define IOMD_IRQREQA __IOMD(0x014)
+#define IOMD_IRQCLRA __IOMD(0x014)
+#define IOMD_IRQMASKA __IOMD(0x018)
+
+#define IOMD_IRQSTATB __IOMD(0x020)
+#define IOMD_IRQREQB __IOMD(0x024)
+#define IOMD_IRQMASKB __IOMD(0x028)
+
+#define IOMD_FIQSTAT __IOMD(0x030)
+#define IOMD_FIQREQ __IOMD(0x034)
+#define IOMD_FIQMASK __IOMD(0x038)
+
+#define IOMD_T0CNTL __IOMD(0x040)
+#define IOMD_T0LTCHL __IOMD(0x040)
+#define IOMD_T0CNTH __IOMD(0x044)
+#define IOMD_T0LTCHH __IOMD(0x044)
+#define IOMD_T0GO __IOMD(0x048)
+#define IOMD_T0LATCH __IOMD(0x04c)
+
+#define IOMD_T1CNTL __IOMD(0x050)
+#define IOMD_T1LTCHL __IOMD(0x050)
+#define IOMD_T1CNTH __IOMD(0x054)
+#define IOMD_T1LTCHH __IOMD(0x054)
+#define IOMD_T1GO __IOMD(0x058)
+#define IOMD_T1LATCH __IOMD(0x05c)
+
+#define IOMD_ROMCR0 __IOMD(0x080)
+#define IOMD_ROMCR1 __IOMD(0x084)
+#define IOMD_DRAMCR __IOMD(0x088)
+#define IOMD_VREFCR __IOMD(0x08C)
+
+#define IOMD_FSIZE __IOMD(0x090)
+#define IOMD_ID0 __IOMD(0x094)
+#define IOMD_ID1 __IOMD(0x098)
+#define IOMD_VERSION __IOMD(0x09C)
+
+#define IOMD_MOUSEX __IOMD(0x0A0)
+#define IOMD_MOUSEY __IOMD(0x0A4)
+
+#define IOMD_DMATCR __IOMD(0x0C0)
+#define IOMD_IOTCR __IOMD(0x0C4)
+#define IOMD_ECTCR __IOMD(0x0C8)
+#define IOMD_DMAEXT __IOMD(0x0CC)
+
+#define DMA_EXT_IO0 1
+#define DMA_EXT_IO1 2
+#define DMA_EXT_IO2 4
+#define DMA_EXT_IO3 8
+
+#define IOMD_IO0CURA __IOMD(0x100)
+#define IOMD_IO0ENDA __IOMD(0x104)
+#define IOMD_IO0CURB __IOMD(0x108)
+#define IOMD_IO0ENDB __IOMD(0x10C)
+#define IOMD_IO0CR __IOMD(0x110)
+#define IOMD_IO0ST __IOMD(0x114)
+
+#define IOMD_IO1CURA __IOMD(0x120)
+#define IOMD_IO1ENDA __IOMD(0x124)
+#define IOMD_IO1CURB __IOMD(0x128)
+#define IOMD_IO1ENDB __IOMD(0x12C)
+#define IOMD_IO1CR __IOMD(0x130)
+#define IOMD_IO1ST __IOMD(0x134)
+
+#define IOMD_IO2CURA __IOMD(0x140)
+#define IOMD_IO2ENDA __IOMD(0x144)
+#define IOMD_IO2CURB __IOMD(0x148)
+#define IOMD_IO2ENDB __IOMD(0x14C)
+#define IOMD_IO2CR __IOMD(0x150)
+#define IOMD_IO2ST __IOMD(0x154)
+
+#define IOMD_IO3CURA __IOMD(0x160)
+#define IOMD_IO3ENDA __IOMD(0x164)
+#define IOMD_IO3CURB __IOMD(0x168)
+#define IOMD_IO3ENDB __IOMD(0x16C)
+#define IOMD_IO3CR __IOMD(0x170)
+#define IOMD_IO3ST __IOMD(0x174)
+
+#define IOMD_SD0CURA __IOMD(0x180)
+#define IOMD_SD0ENDA __IOMD(0x184)
+#define IOMD_SD0CURB __IOMD(0x188)
+#define IOMD_SD0ENDB __IOMD(0x18C)
+#define IOMD_SD0CR __IOMD(0x190)
+#define IOMD_SD0ST __IOMD(0x194)
+
+#define IOMD_SD1CURA __IOMD(0x1A0)
+#define IOMD_SD1ENDA __IOMD(0x1A4)
+#define IOMD_SD1CURB __IOMD(0x1A8)
+#define IOMD_SD1ENDB __IOMD(0x1AC)
+#define IOMD_SD1CR __IOMD(0x1B0)
+#define IOMD_SD1ST __IOMD(0x1B4)
+
+#define IOMD_CURSCUR __IOMD(0x1C0)
+#define IOMD_CURSINIT __IOMD(0x1C4)
+
+#define IOMD_VIDCUR __IOMD(0x1D0)
+#define IOMD_VIDEND __IOMD(0x1D4)
+#define IOMD_VIDSTART __IOMD(0x1D8)
+#define IOMD_VIDINIT __IOMD(0x1DC)
+#define IOMD_VIDCR __IOMD(0x1E0)
+
+#define IOMD_DMASTAT __IOMD(0x1F0)
+#define IOMD_DMAREQ __IOMD(0x1F4)
+#define IOMD_DMAMASK __IOMD(0x1F8)
+
+#define DMA_END_S (1 << 31)
+#define DMA_END_L (1 << 30)
+
+#define DMA_CR_C 0x80
+#define DMA_CR_D 0x40
+#define DMA_CR_E 0x20
+
+#define DMA_ST_OFL 4
+#define DMA_ST_INT 2
+#define DMA_ST_AB 1
+/*
+ * IOC compatability
+ */
+#define IOC_CONTROL IOMD_CONTROL
+#define IOC_IRQSTATA IOMD_IRQSTATA
+#define IOC_IRQREQA IOMD_IRQREQA
+#define IOC_IRQCLRA IOMD_IRQCLRA
+#define IOC_IRQMASKA IOMD_IRQMASKA
+
+#define IOC_IRQSTATB IOMD_IRQSTATB
+#define IOC_IRQREQB IOMD_IRQREQB
+#define IOC_IRQMASKB IOMD_IRQMASKB
+
+#define IOC_FIQSTAT IOMD_FIQSTAT
+#define IOC_FIQREQ IOMD_FIQREQ
+#define IOC_FIQMASK IOMD_FIQMASK
+
+#define IOC_T0CNTL IOMD_T0CNTL
+#define IOC_T0LTCHL IOMD_T0LTCHL
+#define IOC_T0CNTH IOMD_T0CNTH
+#define IOC_T0LTCHH IOMD_T0LTCHH
+#define IOC_T0GO IOMD_T0GO
+#define IOC_T0LATCH IOMD_T0LATCH
+
+#define IOC_T1CNTL IOMD_T1CNTL
+#define IOC_T1LTCHL IOMD_T1LTCHL
+#define IOC_T1CNTH IOMD_T1CNTH
+#define IOC_T1LTCHH IOMD_T1LTCHH
+#define IOC_T1GO IOMD_T1GO
+#define IOC_T1LATCH IOMD_T1LATCH
+
+/*
+ * DMA (MEMC) compatability
+ */
+#define HALF_SAM vram_half_sam
+#define VDMA_ALIGNMENT (HALF_SAM * 2)
+#define VDMA_XFERSIZE (HALF_SAM)
+#define VDMA_INIT IOMD_VIDINIT
+#define VDMA_START IOMD_VIDSTART
+#define VDMA_END IOMD_VIDEND
+
+#ifndef __ASSEMBLER__
+extern unsigned int vram_half_sam;
+#define video_set_dma(start,end,offset) \
+do { \
+ outl (SCREEN_START + start, VDMA_START); \
+ outl (SCREEN_START + end - VDMA_XFERSIZE, VDMA_END); \
+ if (offset >= end - VDMA_XFERSIZE) \
+ offset |= 0x40000000; \
+ outl (SCREEN_START + offset, VDMA_INIT); \
+} while (0)
+#endif
+
* Copyright (C) 1998 Russell King
*
* Event-driven interface for LEDs on machines
+ *
+ * Added led_start and led_stop- Alex Holden, 28th Dec 1998.
*/
#ifndef ASM_ARM_LEDS_H
#define ASM_ARM_LEDS_H
typedef enum {
led_idle_start,
led_idle_end,
- led_timer
+ led_timer,
+ led_start,
+ led_stop
} led_event_t;
/* Use this routine to handle LEDs */
--- /dev/null
+#define VDMA_ALIGNMENT PAGE_SIZE
+#define VDMA_XFERSIZE 16
+#define VDMA_INIT 0
+#define VDMA_START 1
+#define VDMA_END 2
+
+#define video_set_dma(start,end,offset) \
+do { \
+ memc_write (VDMA_START, (start >> 2)); \
+ memc_write (VDMA_END, (end - VDMA_XFERSIZE) >> 2); \
+ memc_write (VDMA_INIT, (offset >> 2)); \
+} while (0)
+
#define __flush_entry_to_ram(entry)
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified. Thus, the following
- * hook is made available.
- */
/* PMD_SHIFT determines the size of the area a second-level page table can map */
#define PMD_SHIFT 20
#define PMD_SIZE (1UL << PMD_SHIFT)
return pte;
}
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified. Thus, the following
+ * hook is made available.
+ */
#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
extern __inline__ unsigned long pte_page(pte_t pte)
/*
* Save the current interrupt enable state & disable IRQs
*/
-#define __save_flags_cli(x) \
- do { \
- unsigned long temp; \
- __asm__ __volatile__( \
-" mov %0, pc\n" \
-" orr %1, %0, #0x08000000\n" \
-" and %0, %0, #0x0c000000\n" \
-" teqp %1, #0\n" \
- : "=r" (x), "=r" (temp) \
- : \
- : "memory"); \
+#define __save_flags_cli(x) \
+ do { \
+ unsigned long temp; \
+ __asm__ __volatile__( \
+" mov %0, pc @ save_flags_cli\n" \
+" orr %1, %0, #0x08000000\n" \
+" and %0, %0, #0x0c000000\n" \
+" teqp %1, #0\n" \
+ : "=r" (x), "=r" (temp) \
+ : \
+ : "memory"); \
} while (0)
/*
* Enable IRQs
*/
-#define __sti() \
- do { \
- unsigned long temp; \
- __asm__ __volatile__( \
-" mov %0, pc\n" \
-" bic %0, %0, #0x08000000\n" \
-" teqp %0, #0\n" \
- : "=r" (temp) \
- : \
- : "memory"); \
+#define __sti() \
+ do { \
+ unsigned long temp; \
+ __asm__ __volatile__( \
+" mov %0, pc @ sti\n" \
+" bic %0, %0, #0x08000000\n" \
+" teqp %0, #0\n" \
+ : "=r" (temp) \
+ : \
+ : "memory"); \
} while(0)
/*
* Disable IRQs
*/
-#define __cli() \
- do { \
- unsigned long temp; \
- __asm__ __volatile__( \
-" mov %0, pc\n" \
-" orr %0, %0, #0x08000000\n" \
-" teqp %0, #0\n" \
- : "=r" (temp) \
- : \
- : "memory"); \
+#define __cli() \
+ do { \
+ unsigned long temp; \
+ __asm__ __volatile__( \
+" mov %0, pc @ cli\n" \
+" orr %0, %0, #0x08000000\n" \
+" teqp %0, #0\n" \
+ : "=r" (temp) \
+ : \
+ : "memory"); \
} while(0)
/*
* save current IRQ & FIQ state
*/
-#define __save_flags(x) \
- do { \
- __asm__ __volatile__( \
-" mov %0, pc\n" \
-" and %0, %0, #0x0c000000\n" \
- : "=r" (x)); \
+#define __save_flags(x) \
+ do { \
+ __asm__ __volatile__( \
+" mov %0, pc @ save_flags\n" \
+" and %0, %0, #0x0c000000\n" \
+ : "=r" (x)); \
} while (0)
/*
* restore saved IRQ & FIQ state
*/
-#define __restore_flags(x) \
- do { \
- unsigned long temp; \
- __asm__ __volatile__( \
-" mov %0, pc\n" \
-" bic %0, %0, #0x0c000000\n" \
-" orr %0, %0, %1\n" \
-" teqp %0, #0\n" \
- : "=r" (temp) \
- : "r" (x) \
- : "memory"); \
+#define __restore_flags(x) \
+ do { \
+ unsigned long temp; \
+ __asm__ __volatile__( \
+" mov %0, pc @ restore_flags\n" \
+" bic %0, %0, #0x0c000000\n" \
+" orr %0, %0, %1\n" \
+" teqp %0, #0\n" \
+ : "=r" (temp) \
+ : "r" (x) \
+ : "memory"); \
} while (0)
#ifdef __SMP__
/*
* An area to invalidate the cache
*/
- alloc_init_section(&start_mem, 0xdf000000, SAFE_ADDR, DOMAIN_KERNEL,
+ alloc_init_section(&start_mem, FLUSH_BASE, FLUSH_BASE_PHYS, DOMAIN_KERNEL,
PMD_SECT_CACHEABLE | PMD_SECT_AP_READ);
/*
#ifndef __ASM_PROC_PAGE_H
#define __ASM_PROC_PAGE_H
+#include <asm/hardware.h>
+
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
/* This handles the memory map.. */
+#ifndef PAGE_OFFSET
#define PAGE_OFFSET 0xc0000000
+#endif
+
#define MAP_NR(addr) (((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT)
#endif /* __KERNEL__ */
*/
extern inline void down(struct semaphore * sem)
{
+ unsigned int cpsr, temp;
+
__asm__ __volatile__ ("
@ atomic down operation
- mrs r0, cpsr
- orr r1, r0, #128 @ disable IRQs
- bic r0, r0, #0x80000000 @ clear N
- msr cpsr, r1
- ldr r1, [%0]
- subs r1, r1, #1
- str r1, [%0]
- orrmi r0, r0, #0x80000000 @ set N
- msr cpsr, r0
- movmi r0, %0
- blmi " SYMBOL_NAME_STR(__down)
- : : "r" (sem) : "r0", "r1", "r2", "r3", "ip", "lr", "cc");
+ mrs %0, cpsr
+ orr %1, %0, #128 @ disable IRQs
+ bic %0, %0, #0x80000000 @ clear N
+ msr cpsr, %1
+ ldr %1, [%2]
+ subs %1, %1, #1
+ orrmi %0, %0, #0x80000000 @ set N
+ str %1, [%2]
+ msr cpsr, %0
+ movmi r0, %2
+ blmi " SYMBOL_NAME_STR(__down_failed)
+ : "=&r" (cpsr), "=&r" (temp)
+ : "r" (sem)
+ : "r0", "lr", "cc");
}
/*
*/
extern inline int down_interruptible (struct semaphore * sem)
{
- int result;
+ unsigned int cpsr, temp;
+
__asm__ __volatile__ ("
- @ atomic down operation
- mrs r0, cpsr
- orr r1, r0, #128 @ disable IRQs
- bic r0, r0, #0x80000000 @ clear N
- msr cpsr, r1
- ldr r1, [%1]
- subs r1, r1, #1
- str r1, [%1]
- orrmi r0, r0, #0x80000000 @ set N
- msr cpsr, r0
- movmi r0, %1
+ @ atomic down interruptible operation
+ mrs %0, cpsr
+ orr %1, %0, #128 @ disable IRQs
+ bic %0, %0, #0x80000000 @ clear N
+ msr cpsr, %1
+ ldr %1, [%2]
+ subs %1, %1, #1
+ orrmi %0, %0, #0x80000000 @ set N
+ str %1, [%2]
+ msr cpsr, %0
+ movmi r0, %2
movpl r0, #0
- blmi " SYMBOL_NAME_STR(__down_interruptible) "
- mov %0, r0"
- : "=r" (result)
+ blmi " SYMBOL_NAME_STR(__down_interruptible_failed) "
+ mov %1, r0"
+ : "=&r" (cpsr), "=&r" (temp)
: "r" (sem)
- : "r0", "r1", "r2", "r3", "ip", "lr", "cc");
- return result;
+ : "r0", "lr", "cc");
+
+ return temp;
}
/*
*/
extern inline void up(struct semaphore * sem)
{
+ unsigned int cpsr, temp;
+
__asm__ __volatile__ ("
@ atomic up operation
- mrs r0, cpsr
- orr r1, r0, #128 @ disable IRQs
- bic r0, r0, #0x80000000 @ clear N
- msr cpsr, r1
- ldr r1, [%0]
- adds r1, r1, #1
- str r1, [%0]
- orrls r0, r0, #0x80000000 @ set N
- msr cpsr, r0
- movmi r0, %0
- blmi " SYMBOL_NAME_STR(__up)
- : : "r" (sem) : "r0", "r1", "r2", "r3", "ip", "lr", "cc");
+ mrs %0, cpsr
+ orr %1, %0, #128 @ disable IRQs
+ bic %0, %0, #0x80000000 @ clear N
+ msr cpsr, %1
+ ldr %1, [%2]
+ adds %1, %1, #1
+ orrls %0, %0, #0x80000000 @ set N
+ str %1, [%2]
+ msr cpsr, %0
+ movmi r0, %2
+ blmi " SYMBOL_NAME_STR(__up_wakeup)
+ : "=&r" (cpsr), "=&r" (temp)
+ : "r" (sem)
+ : "r0", "lr", "cc");
}
#endif
return x;
}
-/*
- * This processor does not need anything special before reset,
- * but RPC may do...
- */
-extern __inline__ void proc_hard_reset(void)
-{
-}
+#define set_cr(x) \
+ do { \
+ __asm__ __volatile__( \
+ "mcr p15, 0, %0, c1, c0 @ set CR" \
+ : : "r" (x)); \
+ } while (0)
+
+extern unsigned long cr_no_alignment; /* defined in entry-armv.S */
+extern unsigned long cr_alignment; /* defined in entry-armv.S */
/*
* We can wait for an interrupt...
*/
-#define proc_idle() \
- do { \
- __asm__ __volatile__( \
-" mcr p15, 0, %0, c15, c8, 2" \
- : : "r" (0)); \
+#define proc_idle() \
+ do { \
+ __asm__ __volatile__( \
+" mcr p15, 0, %0, c15, c8, 2 @ proc_idle" \
+ : : "r" (0)); \
} while (0)
/*
/*
* Save the current interrupt enable state & disable IRQs
*/
-#define __save_flags_cli(x) \
- do { \
- unsigned long temp; \
- __asm__ __volatile__( \
- "mrs %1, cpsr\n" \
-" and %0, %1, #192\n" \
-" orr %1, %1, #128\n" \
-" msr cpsr, %1" \
- : "=r" (x), "=r" (temp) \
- : \
- : "memory"); \
+#define __save_flags_cli(x) \
+ do { \
+ unsigned long temp; \
+ __asm__ __volatile__( \
+ "mrs %1, cpsr @ save_flags_cli\n" \
+" and %0, %1, #192\n" \
+" orr %1, %1, #128\n" \
+" msr cpsr, %1" \
+ : "=r" (x), "=r" (temp) \
+ : \
+ : "memory"); \
} while (0)
/*
* Enable IRQs
*/
-#define __sti() \
- do { \
- unsigned long temp; \
- __asm__ __volatile__( \
- "mrs %0, cpsr\n" \
-" bic %0, %0, #128\n" \
-" msr cpsr, %0" \
- : "=r" (temp) \
- : \
- : "memory"); \
+#define __sti() \
+ do { \
+ unsigned long temp; \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ sti\n" \
+" bic %0, %0, #128\n" \
+" msr cpsr, %0" \
+ : "=r" (temp) \
+ : \
+ : "memory"); \
} while(0)
/*
* Disable IRQs
*/
-#define __cli() \
- do { \
- unsigned long temp; \
- __asm__ __volatile__( \
- "mrs %0, cpsr\n" \
-" orr %0, %0, #128\n" \
-" msr cpsr, %0" \
- : "=r" (temp) \
- : \
- : "memory"); \
+#define __cli() \
+ do { \
+ unsigned long temp; \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ cli\n" \
+" orr %0, %0, #128\n" \
+" msr cpsr, %0" \
+ : "=r" (temp) \
+ : \
+ : "memory"); \
} while(0)
/*
* save current IRQ & FIQ state
*/
-#define __save_flags(x) \
- do { \
- __asm__ __volatile__( \
- "mrs %0, cpsr\n" \
-" and %0, %0, #192" \
- : "=r" (x) \
- : \
- : "memory"); \
+#define __save_flags(x) \
+ do { \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ save_flags\n" \
+" and %0, %0, #192" \
+ : "=r" (x) \
+ : \
+ : "memory"); \
} while (0)
/*
* restore saved IRQ & FIQ state
*/
-#define __restore_flags(x) \
- do { \
- unsigned long temp; \
- __asm__ __volatile__( \
- "mrs %0, cpsr\n" \
-" bic %0, %0, #192\n" \
-" orr %0, %0, %1\n" \
-" msr cpsr, %0" \
- : "=r" (temp) \
- : "r" (x) \
+#define __restore_flags(x) \
+ do { \
+ unsigned long temp; \
+ __asm__ __volatile__( \
+ "mrs %0, cpsr @ restore_flags\n" \
+" bic %0, %0, #192\n" \
+" orr %0, %0, %1\n" \
+" msr cpsr, %0" \
+ : "=r" (temp) \
+ : "r" (x) \
: "memory"); \
} while (0)
/* We use 33-bit arithmetic here... */
#define __range_ok(addr,size) ({ \
unsigned long flag, sum; \
- __asm__ __volatile__("adds %1, %2, %3; sbccs %1, %1, %0; movcc %0, #0" \
+ __asm__ __volatile__("adds %1, %2, %3; sbcccs %1, %1, %0; movcc %0, #0" \
: "=&r" (flag), "=&r" (sum) \
: "r" (addr), "Ir" (size), "0" (current->addr_limit) \
: "cc"); \
#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), 0, NULL })
asmlinkage void __down_failed (void /* special register calling convention */);
-asmlinkage int __down_failed_interruptible (void /* special register calling convention */);
+asmlinkage int __down_interruptible_failed (void /* special register calling convention */);
asmlinkage void __up_wakeup (void /* special register calling convention */);
extern void __down(struct semaphore * sem);
+extern int __down_interruptible(struct semaphore * sem);
extern void __up(struct semaphore * sem);
#define sema_init(sem, val) atomic_set(&((sem)->count), (val))
} sigset_t;
#else
-/* Here we must cater to lics that poke about in kernel headers. */
+/* Here we must cater to libcs that poke about in kernel headers. */
#define NSIG 32
typedef unsigned long sigset_t;
#define SIGRTMIN 32
#define SIGRTMAX (_NSIG-1)
+#define SIGSWI 32
+
/*
* SA_FLAGS values:
*
#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */
#define SA_RESTORER 0x04000000
+#define SA_THIRTYTWO 0x02000000 /* deliver signal in 32-bit mode even if
+ task is running 26 bits. */
/*
* sigaltstack controls
extern inline void init_bh(int nr, void (*routine)(void))
{
bh_base[nr] = routine;
- bh_mask_count[nr] = 0;
+ atomic_set(&bh_mask_count[nr], 0);
bh_mask |= 1 << nr;
}
extern inline void disable_bh(int nr)
{
bh_mask &= ~(1 << nr);
- bh_mask_count[nr]++;
+ atomic_inc(&bh_mask_count[nr]);
synchronize_bh();
}
extern inline void enable_bh(int nr)
{
- if (!--bh_mask_count[nr])
+ if (atomic_dec_and_test(&bh_mask_count[nr]))
bh_mask |= 1 << nr;
}
#ifndef __SMP__
+/*
+ * To be safe, we assume the only compiler that can cope with
+ * empty initialisers is EGCS.
+ */
+#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 90))
+#define EMPTY_INIT_OK
+#endif
+
/*
* Your basic spinlocks, allowing only a single CPU anywhere
*/
-#if (__GNUC__ > 2) || (__GNUC_MINOR__ >= 8)
+#ifdef EMPTY_INIT_OK
typedef struct { } spinlock_t;
-# define SPIN_LOCK_UNLOCKED { }
+# define SPIN_LOCK_UNLOCKED (spinlock_t) { }
#else
typedef unsigned char spinlock_t;
# define SPIN_LOCK_UNLOCKED 0
* irq-safe write-lock, but readers can get non-irqsafe
* read-locks.
*/
-#if (__GNUC__ > 2) || (__GNUC_MINOR__ >= 8)
+#ifdef EMPTY_INIT_OK
typedef struct { } rwlock_t;
-# define RW_LOCK_UNLOCKED { }
+# define RW_LOCK_UNLOCKED (rwlock_t) { }
#else
typedef unsigned char rwlock_t;
# define RW_LOCK_UNLOCKED 0
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
-#define B57600 0010001
-#define B115200 0010002
-#define B230400 0010003
-#define B460800 0010004
+#define B57600 0010001
+#define B115200 0010002
+#define B230400 0010003
+#define B460800 0010004
+#define B500000 0010005
+#define B576000 0010006
+#define B921600 0010007
+#define B1000000 0010010
+#define B1152000 0010011
+#define B1500000 0010012
+#define B2000000 0010013
+#define B2500000 0010014
+#define B3000000 0010015
+#define B3500000 0010016
+#define B4000000 0010017
#define CIBAUD 002003600000 /* input baud rate (not used) */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
#include <asm/arch/timex.h>
+typedef unsigned long cycles_t;
+
+extern cycles_t cacheflush_time;
+
+static inline cycles_t get_cycles (void)
+{
+ return 0;
+}
+
#endif
#define __NR_time (__NR_SYSCALL_BASE+ 13)
#define __NR_mknod (__NR_SYSCALL_BASE+ 14)
#define __NR_chmod (__NR_SYSCALL_BASE+ 15)
-#define __NR_chown (__NR_SYSCALL_BASE+ 16)
+#define __NR_lchown (__NR_SYSCALL_BASE+ 16)
#define __NR_break (__NR_SYSCALL_BASE+ 17)
#define __NR_oldstat (__NR_SYSCALL_BASE+ 18)
#define __NR_lseek (__NR_SYSCALL_BASE+ 19)
#define __NR_rt_sigsuspend (__NR_SYSCALL_BASE+179)
#define __NR_pread (__NR_SYSCALL_BASE+180)
#define __NR_pwrite (__NR_SYSCALL_BASE+181)
-#define __NR_xstat (__NR_SYSCALL_BASE+182)
-#define __NR_xmknod (__NR_SYSCALL_BASE+183)
+#define __NR_chown (__NR_SYSCALL_BASE+182)
+#define __NR_getcwd (__NR_SYSCALL_BASE+183)
+#define __NR_capget (__NR_SYSCALL_BASE+184)
+#define __NR_capset (__NR_SYSCALL_BASE+185)
+#define __NR_sigaltstack (__NR_SYSCALL_BASE+186)
+#define __NR_sendfile (__NR_SYSCALL_BASE+187)
#define __sys2(x) #x
#define __sys1(x) __sys2(x)
#ifdef __KERNEL_SYSCALLS__
-/*
- * we need this inline - forking from kernel space will result
- * in NO COPY ON WRITE (!!!), until an execve is executed. This
- * is no problem, but for the stack. This is handled by not letting
- * main() use the stack at all after fork(). Thus, no function
- * calls - which means inline code for fork too, as otherwise we
- * would use the stack upon exit from 'fork()'.
- *
- * Actually only pause and fork are needed inline, so that there
- * won't be any messing with the stack from main(), but we define
- * some others too.
- */
-#define __NR__exit __NR_exit
-static inline _syscall0(int,idle);
-static inline _syscall0(int,pause);
-static inline _syscall1(int,setup,int,magic);
-static inline _syscall0(int,sync);
-static inline _syscall0(pid_t,setsid);
-static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count);
-static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
-static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count);
-static inline _syscall1(int,dup,int,fd);
-static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp);
-static inline _syscall3(int,open,const char *,file,int,flag,int,mode);
-static inline _syscall1(int,close,int,fd);
-static inline _syscall1(int,_exit,int,exitcode);
-static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options);
-static inline _syscall1(int,delete_module,const char *,name)
+static inline int idle(void)
+{
+ extern int sys_idle(void);
+ return sys_idle();
+}
-static inline pid_t wait(int * wait_stat)
+static inline int pause(void)
+{
+ extern int sys_pause(void);
+ return sys_pause();
+}
+
+static inline int sync(void)
+{
+ extern int sys_sync(void);
+ return sys_sync();
+}
+
+static inline pid_t setsid(void)
+{
+ extern int sys_setsid(void);
+ return sys_setsid();
+}
+
+static inline int write(int fd, const char *buf, off_t count)
+{
+ extern int sys_write(int, const char *, int);
+ return sys_write(fd, buf, count);
+}
+
+static inline int read(int fd, char *buf, off_t count)
+{
+ extern int sys_read(int, char *, int);
+ return sys_read(fd, buf, count);
+}
+
+static inline off_t lseek(int fd, off_t offset, int count)
+{
+ extern off_t sys_lseek(int, off_t, int);
+ return sys_lseek(fd, offset, count);
+}
+
+static inline int dup(int fd)
+{
+ extern int sys_dup(int);
+ return sys_dup(fd);
+}
+
+static inline int open(const char *file, int flag, int mode)
+{
+ extern int sys_open(const char *, int, int);
+ return sys_open(file, flag, mode);
+}
+
+static inline int close(int fd)
{
- return waitpid(-1,wait_stat,0);
+ return sys_close(fd);
}
+static inline int _exit(int exitcode)
+{
+ extern int sys_exit(int);
+ return sys_exit(exitcode);
+}
+static inline pid_t waitpid(pid_t pid, int *wait_stat, int options)
+{
+ extern int sys_wait4(int, int *, int, struct rusage *);
+ return sys_wait4((int)pid, wait_stat, options, NULL);
+}
+
+static inline int delete_module(const char *name)
+{
+ extern int sys_delete_module(const char *name);
+ return sys_delete_module(name);
+}
+
+static inline pid_t wait(int * wait_stat)
+{
+ extern int sys_wait4(int, int *, int, struct rusage *);
+ return sys_wait4(-1, wait_stat, 0, NULL);
+}
+
+/*
+ * The following two can't be eliminated yet - they rely on
+ * specific conditions.
+ */
+static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp);
/*
* This is the mechanism for creating a new kernel thread.
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
-#define B57600 0010001
-#define B115200 0010002
-#define B230400 0010003
-#define B460800 0010004
+#define B57600 0010001
+#define B115200 0010002
+#define B230400 0010003
+#define B460800 0010004
+#define B500000 0010005
+#define B576000 0010006
+#define B921600 0010007
+#define B1000000 0010010
+#define B1152000 0010011
+#define B1500000 0010012
+#define B2000000 0010013
+#define B2500000 0010014
+#define B3000000 0010015
+#define B3500000 0010016
+#define B4000000 0010017
#define CIBAUD 002003600000 /* input baud rate (not used) */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
#define __NR_sendfile 187
#define __NR_getpmsg 188 /* some people actually want streams */
#define __NR_putpmsg 189 /* some people actually want streams */
+#define __NR_vfork 190
/* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */
#define HUPCL 0002000
#define CLOCAL 0004000
#define CBAUDEX 0010000
-#define B57600 0010001
-#define B115200 0010002
-#define B230400 0010003
-#define B460800 0010004
+#define B57600 0010001
+#define B115200 0010002
+#define B230400 0010003
+#define B460800 0010004
+#define B500000 0010005
+#define B576000 0010006
+#define B921600 0010007
+#define B1000000 0010010
+#define B1152000 0010011
+#define B1500000 0010012
+#define B2000000 0010013
+#define B2500000 0010014
+#define B3000000 0010015
+#define B3500000 0010016
+#define B4000000 0010017
#define CIBAUD 002003600000 /* input baud rate (not used) */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
#define CLOCAL 0004000 /* Ignore modem status lines. */
#if defined (__USE_BSD) || defined (__KERNEL__)
#define CBAUDEX 0010000
-#define B57600 0010001
-#define B115200 0010002
-#define B230400 0010003
-#define B460800 0010004
+#define B57600 0010001
+#define B115200 0010002
+#define B230400 0010003
+#define B460800 0010004
+#define B500000 0010005
+#define B576000 0010006
+#define B921600 0010007
+#define B1000000 0010010
+#define B1152000 0010011
+#define B1500000 0010012
+#define B2000000 0010013
+#define B2500000 0010014
+#define B3000000 0010015
+#define B3500000 0010016
+#define B4000000 0010017
#define CIBAUD 002003600000 /* input baud rate (not used) */
#define CMSPAR 010000000000 /* mark or space (stick) parity */
#define CRTSCTS 020000000000 /* flow control */
/*
- * $Id: bitops.h,v 1.10 1998/08/16 21:56:53 geert Exp $
+ * $Id: bitops.h,v 1.11 1999/01/03 20:16:48 cort Exp $
* bitops.h: Bit string operations on the ppc
*/
extern int test_and_clear_bit(int nr, volatile void *addr);
extern int test_and_change_bit(int nr, volatile void *addr);
+
+/* Returns the number of 0's to the left of the most significant 1 bit */
+extern __inline__ int cntlzw(int bits)
+{
+ int lz;
+
+ asm ("cntlzw %0,%1" : "=r" (lz) : "r" (bits));
+ return lz;
+}
+
/*
* These are if'd out here because using : "cc" as a constraint
* results in errors from gcc. -- Cort
#define DMA2_EXT_REG 0x4D6
#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
+#define DMA_AUTOINIT 0x10
extern spinlock_t dma_spin_lock;
extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */
extern void free_dma(unsigned int dmanr); /* release it again */
+#ifdef CONFIG_PCI_QUIRKS
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy (0)
+#endif
+
#endif /* _ASM_DMA_H */
static __inline__ int ide_default_irq(ide_ioreg_t base)
{
- if ( (_machine == _MACH_Pmac) || (_machine == _MACH_mbx) )
+ if ( _machine == _MACH_Pmac )
return 0;
+ else if ( _machine == _MACH_mbx )
+ /* hardcode IRQ 14 on the MBX */
+ return 14+16;
else if ( _machine == _MACH_chrp) {
if (chrp_ide_ports_known == 0)
chrp_ide_probe();
}
/* Convert the shorts/longs in hd_driveid from little to big endian;
- chars are endian independant, of course, but strings need to be flipped.
+ chars are endian independent, of course, but strings need to be flipped.
(Despite what it says in drivers/block/ide.h, they come up as little endian...)
Changes to linux/hdreg.h may require changes here. */
static __inline__ void ide_fix_driveid (struct hd_driveid *id) {
}
}
-
#undef insw
#define insw(port, buf, ns) do { \
if ( _machine == _MACH_chrp) {\
ide_insw((port)+_IO_BASE, (buf), (ns)); \
}\
else if ( (_machine == _MACH_Pmac) || (_machine == _MACH_mbx) ) \
- ide_insw((port), (buf), (ns)); \
+ ide_insw((port)+((_machine==_MACH_mbx)? 0x80000000: 0), \
+ (buf), (ns)); \
else \
/* this must be the same as insw in io.h!! */ \
_insw((unsigned short *)((port)+_IO_BASE), (buf), (ns)); \
if ( _machine == _MACH_chrp) {\
ide_outsw((port)+_IO_BASE, (buf), (ns)); \
}\
- else if ( (_machine == _MACH_Pmac) || (_machine == _MACH_mbx) ) \
- ide_outsw((port), (buf), (ns)); \
+ else if ( (_machine == _MACH_Pmac) || (_machine == _MACH_mbx) ) \
+ ide_outsw((port)+((_machine==_MACH_mbx)? 0x80000000: 0), \
+ (buf), (ns)); \
else \
/* this must be the same as outsw in io.h!! */ \
_outsw((unsigned short *)((port)+_IO_BASE), (buf), (ns)); \
#undef inb
#define inb(port) \
- in_8((unsigned char *)((port) + ((_machine==_MACH_Pmac)? 0: _IO_BASE)))
+ in_8((unsigned char *)((port) + \
+ ((_machine==_MACH_Pmac)? 0: _IO_BASE) + \
+ ((_machine==_MACH_mbx)? 0x80000000: 0)) )
#undef inb_p
#define inb_p(port) inb(port)
#undef outb
#define outb(val, port) \
- out_8((unsigned char *)((port) + ((_machine==_MACH_Pmac)? 0: _IO_BASE)), (val))
+ out_8((unsigned char *)((port) + \
+ ((_machine==_MACH_Pmac)? 0: _IO_BASE) + \
+ ((_machine==_MACH_mbx)? 0x80000000: 0)), (val) )
#undef outb_p
#define outb_p(val, port) outb(val, port)
do { \
unsigned long __pgdir = (unsigned long)pgdir; \
((tsk)->tss.pg_tables = (unsigned long *)(__pgdir)); \
- asm("mtspr %0,%1 \n\t" :: "i"(M_TWB), "r"(__pa(__pgdir))); \
+ asm("mtspr %0,%1 \n\t" : : "i"(M_TWB), "r"(__pa(__pgdir))); \
} while (0)
#endif /* CONFIG_8xx */
/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
#define PageSkip(page) (0)
+#define kern_addr_valid(addr) (1)
+
#endif __ASSEMBLY__
#endif /* _PPC_PGTABLE_H */
#define B115200 00021
#define B230400 00022
#define B460800 00023
+#define B500000 00024
+#define B576000 00025
+#define B921600 00026
+#define B1000000 00027
+#define B1152000 00030
+#define B1500000 00031
+#define B2000000 00032
+#define B2500000 00033
+#define B3000000 00034
+#define B3500000 00035
+#define B4000000 00036
#define CSIZE 00001400
#define CS5 00000000
#define __GFP_LOW 0x02
#define __GFP_MED 0x04
#define __GFP_HIGH 0x08
+#define __GFP_IO 0x10
#define __GFP_DMA 0x80
#define GFP_BUFFER (__GFP_LOW | __GFP_WAIT)
#define GFP_ATOMIC (__GFP_HIGH)
-#define GFP_USER (__GFP_LOW | __GFP_WAIT)
-#define GFP_KERNEL (__GFP_MED | __GFP_WAIT)
-#define GFP_NFS (__GFP_HIGH | __GFP_WAIT)
+#define GFP_USER (__GFP_LOW | __GFP_WAIT | __GFP_IO)
+#define GFP_KERNEL (__GFP_MED | __GFP_WAIT | __GFP_IO)
+#define GFP_NFS (__GFP_HIGH | __GFP_WAIT | __GFP_IO)
/* Flag - indicates that the buffer will be suitable for DMA. Ignored on some
platforms, used as appropriate on others */
extern int init_nls_iso8859_7(void);
extern int init_nls_iso8859_8(void);
extern int init_nls_iso8859_9(void);
+extern int init_nls_iso8859_15(void);
extern int init_nls_cp437(void);
extern int init_nls_cp737(void);
extern int init_nls_cp775(void);
/* Pointer to task[] array linkage. */
struct task_struct **tarray_ptr;
- struct wait_queue *wait_chldexit; /* for wait4() */
+ struct wait_queue *wait_chldexit, *vfork_sleep; /* for wait4()/vfork */
+
unsigned long policy, rt_priority;
unsigned long it_real_value, it_prof_value, it_virt_value;
unsigned long it_real_incr, it_prof_incr, it_virt_incr;
struct files_struct *files;
/* memory management info */
struct mm_struct *mm;
+
/* signal handlers */
spinlock_t sigmask_lock; /* Protects signal and blocked */
struct signal_struct *sig;
/* proc links*/ &init_task,&init_task,NULL,NULL,NULL, \
/* pidhash */ NULL, NULL, \
/* tarray */ &task[0], \
-/* chld wait */ NULL, \
+/* chld wait */ NULL, NULL, \
/* timeout */ SCHED_OTHER,0,0,0,0,0,0,0, \
/* timer */ { NULL, NULL, 0, 0, it_real_fn }, \
/* utime */ {0,0,0,0},0, \
#ifndef _LINUX_SUNRPC_STATS_H
#define _LINUX_SUNRPC_STATS_H
+#include <linux/config.h>
#include <linux/proc_fs.h>
struct rpc_stat {
*/
union { /* record marker & XID */
u32 header[2];
- u8 * data[8];
+ u8 data[8];
} tcp_recm;
struct rpc_rqst * tcp_rqstp;
struct iovec tcp_iovec[MAX_IOVEC];
int canon_data;
unsigned long canon_head;
unsigned int canon_column;
+ struct semaphore atomic_read;
};
/* tty magic number */
#define TTY_DO_WRITE_WAKEUP 5
#define TTY_PUSH 6
#define TTY_CLOSING 7
+#define TTY_DONT_FLIP 8
#define TTY_HW_COOK_OUT 14
#define TTY_HW_COOK_IN 15
#define TTY_PTY_LOCK 16
#define UFS_MOUNT_ONERROR_UMOUNT 0x00000004
#define UFS_MOUNT_ONERROR_REPAIR 0x00000008
-#define UFS_MOUNT_UFSTYPE 0x000000F0
+#define UFS_MOUNT_UFSTYPE 0x000001F0
#define UFS_MOUNT_UFSTYPE_OLD 0x00000010
#define UFS_MOUNT_UFSTYPE_44BSD 0x00000020
#define UFS_MOUNT_UFSTYPE_SUN 0x00000040
#define UFS_MOUNT_UFSTYPE_NEXT 0x00000080
-
+#define UFS_MOUNT_UFSTYPE_OPENSTEP 0x00000100
#define ufs_clear_opt(o,opt) o &= ~UFS_MOUNT_##opt
#define ufs_set_opt(o,opt) o |= UFS_MOUNT_##opt
/* externs */
extern struct br_stat br_stats;
-
+extern Port_data port_info[];
#define IP_MASQ_F_NO_SADDR 0x0004 /* no sport set yet */
#define IP_MASQ_F_NO_SPORT 0x0008 /* no sport set yet */
-#define IP_MASQ_F_NO_REPLY 0x0010 /* no reply yet from outside */
+#define IP_MASQ_F_DLOOSE 0x0010 /* loose dest binding */
+#define IP_MASQ_F_NO_REPLY 0x0080 /* no reply yet from outside */
#define IP_MASQ_F_HASHED 0x0100 /* hashed entry */
#define IP_MASQ_F_OUT_SEQ 0x0200 /* must do output seq adjust */
kill_pg(current->pgrp,SIGHUP,1);
kill_pg(current->pgrp,SIGCONT,1);
}
+
/* Let father know we died */
notify_parent(current, current->exit_signal);
*/
void mmput(struct mm_struct *mm)
{
+ /* notify parent sleeping on vfork() */
+ wake_up(¤t->p_opptr->vfork_sleep);
+
if (atomic_dec_and_test(&mm->count)) {
release_segments(mm);
exit_mmap(mm);
p->p_pptr = p->p_opptr = current;
p->p_cptr = NULL;
init_waitqueue(&p->wait_chldexit);
+ init_waitqueue(&p->vfork_sleep);
p->sigpending = 0;
sigemptyset(&p->signal);
* a bad memory situation, we're better off trying
* to free things up until things are better.
*
- * Normally we shouldn't ever have to do this, with
- * kswapd doing this in the background.
- *
* Most notably, this puts most of the onus of
* freeing up memory on the processes that _use_
* the most memory, rather than on everybody.
{
int freed;
current->flags |= PF_MEMALLOC;
- freed = try_to_free_pages(gfp_mask, SWAP_CLUSTER_MAX);
+ freed = try_to_free_pages(gfp_mask, freepages.high - nr_free_pages);
current->flags &= ~PF_MEMALLOC;
if (!freed && !(gfp_mask & (__GFP_MED | __GFP_HIGH)))
goto nopage;
set_pte(page_table, __pte(entry));
drop_pte:
vma->vm_mm->rss--;
- tsk->nswap++;
flush_tlb_page(vma, address);
__free_page(page_map);
return 0;
goto drop_pte;
}
+ /*
+ * Don't go down into the swap-out stuff if
+ * we cannot do I/O! Avoid recursing on FS
+ * locks etc.
+ */
+ if (!(gfp_mask & __GFP_IO))
+ return 0;
+
/*
* Ok, it's really dirty. That means that
* we should either create a new swap cache
return NULL;
}
skb->dev = dev;
- skb->mac.raw = skb->h.raw = skb_put(skb,size);
- memset(skb->h.raw + 60 - pad_size, 0xa5, pad_size);
+ skb->mac.raw = skb->nh.raw = skb_put(skb,size);
+ memset(skb->nh.raw + 60 - pad_size, 0xa5, pad_size);
eth = skb->mac.ethernet;
memcpy(eth->h_dest, bridge_ula, ETH_ALEN);
memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
#endif
eth->h_proto = htons(pdu_size + BRIDGE_LLC1_HS);
- skb->h.raw += skb->dev->hard_header_len;
- llc_buffer = skb->h.raw;
+ skb->nh.raw += skb->dev->hard_header_len;
+ llc_buffer = skb->nh.raw;
*llc_buffer++ = BRIDGE_LLC1_DSAP;
*llc_buffer++ = BRIDGE_LLC1_SSAP;
*llc_buffer++ = BRIDGE_LLC1_CTRL;
- /* set h.raw to where the bpdu starts */
- skb->h.raw += BRIDGE_LLC1_HS;
+ /* set nh.raw to where the bpdu starts */
+ skb->nh.raw += BRIDGE_LLC1_HS;
/* mark that we've been here... */
skb->pkt_bridged = IS_BRIDGED;
return(-1);
/* copy fields before "flags" */
- memcpy(skb->h.raw, config_bpdu, BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
+ memcpy(skb->nh.raw, config_bpdu, BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
/* build the "flags" field */
- *(skb->h.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) = 0;
+ *(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) = 0;
if (config_bpdu->top_change_ack)
- *(skb->h.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) |= 0x80;
+ *(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) |= 0x80;
if (config_bpdu->top_change)
- *(skb->h.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) |= 0x01;
+ *(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET) |= 0x01;
config_bpdu_hton(config_bpdu);
/* copy the rest */
- memcpy(skb->h.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET+1,
+ memcpy(skb->nh.raw+BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET+1,
(char*)&(config_bpdu->root_id),
BRIDGE_BPDU_8021_CONFIG_SIZE-1-BRIDGE_BPDU_8021_CONFIG_FLAG_OFFSET);
if (skb == NULL)
return(-1);
- memcpy(skb->h.raw, bpdu, sizeof(Tcn_bpdu));
+ memcpy(skb->nh.raw, bpdu, sizeof(Tcn_bpdu));
dev_queue_xmit(skb);
return(0);
if(!port)
return 0;
- skb->h.raw = skb->mac.raw;
+ skb->nh.raw = skb->mac.raw;
eth = skb->mac.ethernet;
p = &port_info[port];
return(0);
}
++br_stats_cnt.port_not_disable;
- skb->mac.raw = skb->h.raw = skb->data;
+ skb->mac.raw = skb->nh.raw = skb->data;
eth = skb->mac.ethernet;
port = 0; /* an impossible port (locally generated) */
if (br_stats.flags & BR_DEBUG)
skb->pkt_bridged = IS_BRIDGED;
/* reset the skb->ip pointer */
- skb->h.raw = skb->data + ETH_HLEN;
+ skb->nh.raw = skb->data + ETH_HLEN;
/*
* Send the buffer out.
or have a received valid MAC header */
/* printk("Flood to port %d\n",i);*/
- nskb->h.raw = nskb->data + ETH_HLEN;
+ nskb->nh.raw = nskb->data + ETH_HLEN;
#if LINUX_VERSION_CODE >= 0x20100
nskb->priority = 1;
dev_queue_xmit(nskb);
#include <linux/string.h>
#include <linux/malloc.h>
#include <linux/skbuff.h>
+#include <linux/netdevice.h>
#include <net/br.h>
#define _DEBUG_AVL
static struct fdb **fhpp = &fhp;
static int fdb_inited = 0;
+#ifdef DEBUG_AVL
+static void printk_avl (struct fdb * tree);
+#endif
+
static int addr_cmp(unsigned char *a1, unsigned char *a2);
/*
addr[4],
addr[5]);
#endif /* DEBUG_AVL */
- for (tree = &fdb_head ; ; ) {
+ for (tree = fhp ; ; ) {
if (tree == avl_br_empty) {
#if (DEBUG_AVL)
printk("search failed, returning node 0x%x\n", (unsigned int)result);
/* don't write the local device */
if(tree->port != 0){
size = sprintf(*pbuffer,
- "%02x:%02x:%02x:%02x:%02x:%02x eth%d %d %d\n",
+ "%02x:%02x:%02x:%02x:%02x:%02x %s %d %ld\n",
tree->ula[0],tree->ula[1],tree->ula[2],
tree->ula[3],tree->ula[4],tree->ula[5],
- tree->port-1, tree->flags,CURRENT_TIME-tree->timer);
+ port_info[tree->port].dev->name, tree->flags,CURRENT_TIME-tree->timer);
(*pos)+=size;
(*len)+=size;
extern void dlci_setup(void);
extern int dmascc_init(void);
extern int sm_init(void);
-extern int baycom_init(void);
+
+extern int baycom_ser_fdx_init(void);
+extern int baycom_ser_hdx_init(void);
+extern int baycom_par_init(void);
+
extern int lapbeth_init(void);
extern void arcnet_init(void);
extern void ip_auto_config(void);
#if defined(CONFIG_SDLA)
sdla_setup();
#endif
-#if defined(CONFIG_BAYCOM)
- baycom_init();
+#if defined(CONFIG_BAYCOM_PAR)
+ baycom_par_init();
+#endif
+#if defined(CONFIG_BAYCOM_SER_FDX)
+ baycom_ser_fdx_init();
+#endif
+#if defined(CONFIG_BAYCOM_SER_HDX)
+ baycom_ser_hdx_init();
#endif
#if defined(CONFIG_SOUNDMODEM)
sm_init();
* 1-May-1998: Remove caching of device pointer.
* 12-May-1998: Allow tiny fragment case for TCP/UDP.
* 15-May-1998: Treat short packets as fragments, don't just block.
+ * 3-Jan-1999: Fixed serious procfs security hole -- users should never
+ * be allowed to view the chains!
+ * Marc Santoro <ultima@snicker.emoti.com>
*/
/*
printk("%s\n",chain->label);
}
-static inline void
+static inline int
ip_fw_domatch(struct ip_fwkernel *f,
struct iphdr *ip,
const char *rif,
len-(sizeof(__u32)*2+IFNAMSIZ));
netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_KERNEL);
}
- else duprintf("netlink post failed - alloc_skb failed!\n");
+ else {
+ if (net_ratelimit())
+ printk(KERN_WARNING "ip_fw: packet drop due to "
+ "netlink failure\n");
+ return 0;
+ }
}
#endif
+ return 1;
}
/*
for (; f; f = f->next) {
if (ip_rule_match(f,rif,ip,
tcpsyn,src_port,dst_port,offset)) {
- if (!testing)
- ip_fw_domatch(f, ip, rif, chain->label, skb,
- slot, src_port,dst_port);
+ if (!testing
+ && !ip_fw_domatch(f, ip, rif, chain->label,
+ skb, slot,
+ src_port, dst_port)) {
+ ret = FW_BLOCK;
+ goto out;
+ }
break;
}
}
}
} while (ret == FW_SKIP+2);
+ out:
if (!testing) FWC_READ_UNLOCK(&ip_fw_lock);
/* Recalculate checksum if not going to reject, and TOS changed. */
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry proc_net_ipfwchains_chain = {
PROC_NET_IPFW_CHAINS, sizeof(IP_FW_PROC_CHAINS)-1,
- IP_FW_PROC_CHAINS, S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+ IP_FW_PROC_CHAINS, S_IFREG | S_IRUSR | S_IWUSR, 1, 0, 0,
0, &proc_net_inode_operations, ip_chain_procinfo
};
static struct proc_dir_entry proc_net_ipfwchains_chainnames = {
PROC_NET_IPFW_CHAIN_NAMES, sizeof(IP_FW_PROC_CHAIN_NAMES)-1,
- IP_FW_PROC_CHAIN_NAMES, S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+ IP_FW_PROC_CHAIN_NAMES, S_IFREG | S_IRUSR | S_IWUSR, 1, 0, 0,
0, &proc_net_inode_operations, ip_chain_name_procinfo
};
* FIXME: the *_user functions should
* return how much data was
* copied before the fault
- * occured and then a partial
+ * occurred and then a partial
* packet with this data should
* be sent. Unfortunately
* csum_and_copy_from_user doesn't
* Now it should be a CONNREQ.
*/
if (frametype != NR_CONNREQ) {
+ /*
+ * Here it would be nice to be able to send a reset but
+ * NET/ROM doesn't have one. The following hack would
+ * have been a way to extend the protocol but apparently
+ * it kills BPQ boxes... :-(
+ */
+#if 0
/*
* Never reply to a CONNACK/CHOKE.
*/
if (frametype != NR_CONNACK || flags != NR_CHOKE_FLAG)
nr_transmit_refusal(skb, 1);
-
+#endif
return 0;
}
defined(CONFIG_E2100) || defined(CONFIG_HPLAN_PLUS) || \
defined(CONFIG_HPLAN) || defined(CONFIG_AC3200) || \
defined(CONFIG_ES3210) || defined(CONFIG_ULTRA32) || \
- defined(CONFIG_LNE390) || defined(CONFIG_NE3210)
+ defined(CONFIG_LNE390) || defined(CONFIG_NE3210) || \
+ defined(CONFIG_NE2K_PCI) || defined(CONFIG_APNE) || \
+ defined(CONFIG_DAYNAPORT)
#include "../drivers/net/8390.h"
#endif
defined(CONFIG_E2100) || defined(CONFIG_HPLAN_PLUS) || \
defined(CONFIG_HPLAN) || defined(CONFIG_AC3200) || \
defined(CONFIG_ES3210) || defined(CONFIG_ULTRA32) || \
- defined(CONFIG_LNE390) || defined(CONFIG_NE3210)
+ defined(CONFIG_LNE390) || defined(CONFIG_NE3210) || \
+ defined(CONFIG_NE2K_PCI) || defined(CONFIG_APNE) || \
+ defined(CONFIG_DAYNAPORT)
/* If 8390 NIC support is built in, we will need these. */
EXPORT_SYMBOL(ei_open);
EXPORT_SYMBOL(ei_close);
---enqueue
enqueue returns number of enqueued packets i.e. this number is 1,
- if packet was enqueued sucessfully and <1 if something (not
+ if packet was enqueued successfully and <1 if something (not
necessary THIS packet) was dropped.
Auxiliary routines:
}
#ifdef CSZ_PLUS_TBF
/* We are about to return no skb.
- Schedule watchdog timer, if it occured because of shaping.
+ Schedule watchdog timer, if it occurred because of shaping.
*/
if (q->wd_expires) {
unsigned long delay = PSCHED_US2JIFFIE(q->wd_expires);
}
save_flags(oldflags); cli();
if (!schedq.task) {
+ /* following two lines added by airlied@linux.ie
+ to make NFS over TCP work 5/1/99 */
+ dprintk("RPC: rpciod running checking dispatch\n");
+ rpciod_tcp_dispatcher();
dprintk("RPC: rpciod back to sleep\n");
interruptible_sleep_on(&rpciod_idle);
dprintk("RPC: switch to rpciod\n");
* impossible at the moment.
*/
+#include <linux/config.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/linkage.h>
*/
if (!xprt->rx_pending_flag)
{
- dprintk("RPC: xprt queue\n");
+ int start_queue=0;
+
+ dprintk("RPC: xprt queue %p\n", rpc_xprt_pending);
if(rpc_xprt_pending==NULL)
- tcp_rpciod_queue();
+ start_queue=1;
xprt->rx_pending_flag=1;
xprt->rx_pending=rpc_xprt_pending;
rpc_xprt_pending=xprt;
+ if (start_queue)
+ {
+ tcp_rpciod_queue();
+ start_queue=0;
+ }
}
else
dprintk("RPC: xprt queued already %p\n", xprt);
eval $cmd
}
if [regexp {([0-9A-Za-z_]+)="([^"]*)"} $line foo var value] {
- set cmd "global $var; set $var $value"
+ set cmd "global $var; set $var \"$value\""
eval $cmd
}
}
#define GETNEXT { \
next_byte(__buf); \
if ((unsigned long) next % sizeof(unsigned long) == 0) { \
- __buf = * (unsigned long *) next; \
- if (!__buf) \
+ if (next >= end) \
break; \
+ __buf = * (unsigned long *) next; \
} \
next++; \
}
* per memory read. The MAX6 and MIN6 tests dispose of most
* input characters with 1 or 2 comparisons.
*/
-void state_machine(const char * map)
+void state_machine(const char * map, const char * end)
{
const char * next = map;
const char * map_dot;
return;
}
- mapsize = st.st_size + 2*sizeof(unsigned long);
+ mapsize = st.st_size;
mapsize = (mapsize+pagesizem1) & ~pagesizem1;
map = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
if ((long) map == -1) {
hasdep = 0;
clear_config();
- state_machine(map);
+ state_machine(map, map+st.st_size);
if (hasdep)
puts(command);
* Generate the code to close out the last menu.
*/
end_proc(menu_num);
+ clear_globalflags(config);
/*
* The top level menu also needs an update function. When we exit a
--- /dev/null
+#!/bin/sh
+# Before running this script please ensure that your PATH is
+# typical as you use for compilation/istallation. I use
+# /bin /sbin /usr/bin /usr/sbin /usr/local/bin, but it may
+# differs on your system.
+#
+echo '-- Versions installed: (if some fields are empty or looks'
+echo '-- unusual then possibly you have very old versions)'
+uname -a
+insmod -V 1>/tmp/ver_linux.tmp 2>>/tmp/ver_linux.tmp
+awk 'NR==1{print "Kernel modules ",$NF}' /tmp/ver_linux.tmp
+rm -f /tmp/ver_linux.tmp
+echo "Gnu C " `gcc --version`
+ld -v 2>&1 | awk -F\) '{print $1}' | awk \
+ '/BFD/{print "Binutils ",$NF}'
+ls -l `ldd /bin/sh | awk '/libc/{print $3}'` | sed -e 's/\.so$//' \
+ | awk -F'[.-]' '{print "Linux C Library " $(NF-2)"."$(NF-1)"."$NF}'
+echo -n "Dynamic linker "
+ldd -v > /dev/null 2>&1 && ldd -v || ldd --version |head -1
+ls -l /usr/lib/lib{g,stdc}++.so 2>/dev/null | awk -F. \
+ '{print "Linux C++ Library " $4"."$5"."$6}'
+ps --version 2>&1 | awk 'NR==1{print "Procps ", $NF}'
+mount --version | awk -F\- '{print "Mount ", $NF}'
+netstat --version | awk \
+'NR==1{if ($5 != "") { n=split($5,buf,"-"); ver=buf[n]; done=1 }}
+ NR==2{if (done != 1) ver=$3 }
+ END{print "Net-tools ",ver}'
+loadkeys -h 2>&1 | awk 'NR==1{print "Kbd ",$3}'
+expr --v | awk '{print "Sh-utils ", $NF}'