diff -u --recursive --new-file v2.3.99-pre8/linux/CREDITS linux/CREDITS --- v2.3.99-pre8/linux/CREDITS Wed Apr 26 16:34:06 2000 +++ linux/CREDITS Sat May 20 11:39:56 2000 @@ -251,6 +251,14 @@ S: 6369 BG Simpelveld S: The Netherlands +N: Peter Berger +E: pberger@brimson.com +W: http://www.brimson.com +D: Author/maintainer of Digi AccelePort USB driver +S: 1549 Hiironen Rd. +S: Brimson, MN 55602 +S: USA + N: Hennus Bergman E: hennus@cybercomm.nl W: http://www.cybercomm.nl/~hennus/ @@ -318,6 +326,13 @@ D: IEEE 1394 subsystem rewrite and maintainer D: Texas Instruments PCILynx IEEE 1394 driver +N: Al Borchers +E: alborchers@steinerpoint.com +D: Author/maintainer of Digi AccelePort USB driver +S: 4912 Zenith Ave. S. +S: Minneapolis, MN 55410 +S: USA + N: Marc Boucher E: marc@mbsi.ca P: CA 67 A5 1A 38 CE B6 F2 D5 83 51 03 D2 9C 30 9E CE D2 DD 65 @@ -942,14 +957,20 @@ N: Andre Hedrick E: andre@linux-ide.org +E: ahedrick@atipa.com E: andre@suse.com +W: http://www.linux-ide.org/ D: Random SMP kernel hacker... D: Uniform Multi-Platform E-IDE driver D: Active-ATA-Chipset maddness.......... D: Ultra DMA 66/33 D: ATA-Smart Kernel Daemon -S: 580 Second Street, Suite 2 -S: Oakland, CA +S: Linux ATA Development (LAD) +S: Concord, CA +S: Atipa Linux Solutions +S: 6000 Connecticut Kansas City, MO 64120 +S: SuSE Linux, Inc. +S: 580 Second Street, Suite 210 Oakland, CA 94607 S: USA N: Jochen Hein @@ -1607,12 +1628,30 @@ D: XF86_8514 D: cfdisk (curses based disk partitioning program) +N: Claudio S. Matsuoka +E: claudio@conectiva.com +E: claudio@helllabs.org +W: http://helllabs.org/~claudio +D: OV511 driver hacks +S: Conectiva S.A. +S: R. Tocantins 89 +S: 80050-430 Curitiba PR +S: Brazil + N: Heinz Mauelshagen E: mge@EZ-Darmstadt.Telekom.de D: Logical Volume Manager S: Bartningstr. 12 S: 64289 Darmstadt S: Germany + +N: Mark W. McClelland +E: mmcclelland@delphi.com +E: mark@alpha.dyndns.org +W: http://alpha.dyndns.org/ov511/ +D: OV511 driver +S: (address available on request) +S: USA N: Mike McLagan E: mike.mclagan@linux.org diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.3.99-pre8/linux/Documentation/Configure.help Fri May 12 14:18:55 2000 +++ linux/Documentation/Configure.help Tue May 23 08:22:22 2000 @@ -1496,7 +1496,7 @@ If unsure, say Y. -DANGEROUS! RAID-1/RAID-5 code +RAID-1/RAID-5 code (DANGEROUS) CONFIG_RAID15_DANGEROUS This new RAID1/RAID5 code has been freshly merged, and has not seen enough testing yet. While there are no known bugs in it, it might @@ -9779,6 +9779,12 @@ CONFIG_USB_SERIAL_OMNINET Say Y here if you want to use a ZyXEL omni.net LCD ISDN TA. +USB Digi International AccelePort USB Serial Driver +CONFIG_USB_SERIAL_DIGI_ACCELEPORT + Say Y here if you want to use a Digi AccelePort USB 4 device, + a 4 port USB serial converter. The Digi Acceleport USB 2 and + 8 are not yet supported by this driver. + USB Printer support CONFIG_USB_PRINTER Say Y here if you want to connect a USB printer to your computer's @@ -10430,7 +10436,7 @@ Provide NFSv3 server support CONFIG_NFSD_V3 If you would like to include the NFSv3 server as well as the NFSv2 - server, say Y here. In unsure, say Y. + server, say Y here. If unsure, say Y. OS/2 HPFS file system support CONFIG_HPFS_FS @@ -12461,14 +12467,6 @@ option doesn't work for all laptops -- it might not turn off your backlight at all, or it might print a lot of errors to the console, especially if you are using gpm. - -Ignore multiple suspend/standby events -CONFIG_APM_IGNORE_MULTIPLE_SUSPEND - This option is necessary on the IBM Thinkpad 560, but should work on - all other laptops. When the APM BIOS returns multiple suspend or - standby events while one is already being processed they will be - ignored. Without this the Thinkpad 560 has troubles with the user - level daemon apmd, and with the PCMCIA package pcmcia-cs. Ignore multiple suspend/resume cycles CONFIG_APM_IGNORE_SUSPEND_BOUNCE diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile --- v2.3.99-pre8/linux/Documentation/DocBook/Makefile Wed Apr 26 16:34:06 2000 +++ linux/Documentation/DocBook/Makefile Sun May 21 20:18:07 2000 @@ -1,4 +1,4 @@ -BOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml kernel-api.sgml parportbook.sgml +BOOKS := wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml kernel-api.sgml parportbook.sgml kernel-hacking.sgml kernel-locking.sgml PS := $(patsubst %.sgml, %.ps, $(BOOKS)) PDF := $(patsubst %.sgml, %.pdf, $(BOOKS)) @@ -18,6 +18,9 @@ (echo "*** You need to install DocBook stylesheets ***"; \ exit 1) +%.eps: %.fig + -fig2dev -Leps $< $@ + $(TOPDIR)/scripts/docproc: $(MAKE) -C $(TOPDIR)/scripts docproc @@ -51,6 +54,7 @@ $(TOPDIR)/drivers/sound/sound_firmware.c \ $(TOPDIR)/drivers/net/wan/syncppp.c \ $(TOPDIR)/drivers/net/wan/z85230.c \ + $(TOPDIR)/fs/devfs/base.c \ $(TOPDIR)/kernel/pm.c \ $(TOPDIR)/kernel/ksyms.c \ $(TOPDIR)/net/netsyms.c \ @@ -66,12 +70,15 @@ LOG := $(patsubst %.sgml, %.log, $(BOOKS)) clean: - $(RM) core *~ - $(RM) $(BOOKS) - $(RM) $(DVI) $(AUX) $(TEX) $(LOG) + -$(RM) core *~ + -$(RM) $(BOOKS) + -$(RM) $(DVI) $(AUX) $(TEX) $(LOG) + -$(RM) parport-share.eps parport-multi.eps parport-structure.eps mrproper: clean - $(RM) $(PS) $(PDF) + -$(RM) $(PS) $(PDF) + +parportbook.ps: parport-share.eps parport-multi.eps parport-structure.eps %.ps : %.sgml db2ps db2ps $< diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/DocBook/kernel-api.tmpl linux/Documentation/DocBook/kernel-api.tmpl --- v2.3.99-pre8/linux/Documentation/DocBook/kernel-api.tmpl Tue Apr 11 15:09:11 2000 +++ linux/Documentation/DocBook/kernel-api.tmpl Sat May 13 08:11:27 2000 @@ -101,6 +101,11 @@ + + The Device File System +!Efs/devfs/base.c + + Power Management !Ekernel/pm.c diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/DocBook/kernel-hacking.tmpl linux/Documentation/DocBook/kernel-hacking.tmpl --- v2.3.99-pre8/linux/Documentation/DocBook/kernel-hacking.tmpl Wed Dec 31 16:00:00 1969 +++ linux/Documentation/DocBook/kernel-hacking.tmpl Sun May 21 20:18:07 2000 @@ -0,0 +1,1316 @@ + + + + + Unreliable Guide To Hacking The Linux Kernel + + + + Paul + Rusty + Russell + +
+ rusty@linuxcare.com +
+
+
+
+ + + 2000 + Paul Russell + + + + + This documentation 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 (at your option) any later + version. + + + + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + + + + This is the first release of this document as part of the kernel tarball. + + +
+ + + + + Introduction + + Welcome, gentle reader, to Rusty's Unreliable Guide to Linux + Kernel Hacking. This document describes the common routines and + general requirements for kernel code: its goal is to serve as a + primer for Linux kernel development for experienced C + programmers. I avoid implementation details: that's what the + code is for, and I ignore whole tracts of useful routines. + + + Before you read this, please understand that I never wanted to + write this document, being grossly under-qualified, but I always + wanted to read it, and this was the only way. I hope it will + grow into a compendium of best practice, common starting points + and random information. + + + + + The Players + + + At any time each of the CPUs in a system can be: + + + + + + not associated with any process, serving a hardware interrupt; + + + + + + not associated with any process, serving a softirq, tasklet or bh; + + + + + + running in kernel space, associated with a process; + + + + + + running a process in user space. + + + + + + There is a strict ordering between these: other than the last + category (userspace) each can only be pre-empted by those above. + For example, while a softirq is running on a CPU, no other + softirq will pre-empt it, but a hardware interrupt can. However, + any other CPUs in the system execute independently. + + + + We'll see a number of ways that the user context can block + interrupts, to become truly non-preemptable. + + + + User Context + + + User context is when you are coming in from a system call or + other trap: you can sleep, and you own the CPU (except for + interrupts) until you call schedule(). + In other words, user context (unlike userspace) is not pre-emptable. + + + + + You are always in user context on module load and unload, + and on operations on the block device layer. + + + + + In user context, the current pointer (indicating + the task we are currently executing) is valid, and + in_interrupt() + (include/asm/hardirq.h) is false + . + + + + + Beware that if you have interrupts or bottom halves disabled + (see below), in_interrupt() will return a + false positive. + + + + + + Hardware Interrupts (Hard IRQs) + + + Timer ticks, network cards and + keyboard are examples of real + hardware which produce interrupts at any time. The kernel runs + interrupt handlers, which services the hardware. The kernel + guarantees that this handler is never re-entered: if another + interrupt arrives, it is queued (or dropped). Because it + disables interrupts, this handler has to be fast: frequently it + simply acknowledges the interrupt, marks a `software interrupt' + for execution and exits. + + + + You can tell you are in a hardware interrupt, because + in_irq() returns true. + + + + Beware that this will return a false positive if interrupts are disabled + (see below). + + + + + + Software Interrupt Context: Bottom Halves, Tasklets, softirqs + + + Whenever a system call is about to return to userspace, or a + hardware interrupt handler exits, any `software interrupts' + which are marked pending (usually by hardware interrupts) are + run (kernel/softirq.c). + + + + Much of the real interrupt handling work is done here. Early in + the transition to SMP, there were only `bottom + halves' (BHs), which didn't take advantage of multiple CPUs. Shortly + after we switched from wind-up computers made of match-sticks and snot, + we abandoned this limitation. + + + + include/linux/interrupt.h lists the + different BH's. No matter how many CPUs you have, no two BHs will run at + the same time. This made the transition to SMP simpler, but sucks hard for + scalable performance. A very important bottom half is the timer + BH (include/linux/timer.h): you + can register to have it call functions for you in a given length of time. + + + + 2.3.43 introduced softirqs, and re-implemented the (now + deprecated) BHs underneath them. Softirqs are fully-SMP + versions of BHs: they can run on as many CPUs at once as + required. This means they need to deal with any races in shared + data using their own locks. A bitmask is used to keep track of + which are enabled, so the 32 available softirqs should not be + used up lightly. (Yes, people will + notice). + + + + tasklets (include/linux/interrupt.h) + are like softirqs, except they are dynamically-registrable (meaning you + can have as many as you want), and they also guarantee that any tasklet + will only run on one CPU at any time, although different tasklets can + run simultaneously (unlike different BHs). + + + + The name `tasklet' is misleading: they have nothing to do with `tasks', + and probably more to do with some bad vodka Alexey Kuznetsov had at the + time. + + + + + You can tell you are in a softirq (or bottom half, or tasklet) + using the in_softirq() macro + (include/asm/softirq.h). + + + + Beware that this will return a false positive if a bh lock (see below) + is held. + + + + + + + Some Basic Rules + + + + No memory protection + + + If you corrupt memory, whether in user context or + interrupt context, the whole machine will crash. Are you + sure you can't do what you want in userspace? + + + + + + No floating point or MMX + + + The FPU context is not saved; even in user + context the FPU state probably won't + correspond with the current process: you would mess with some + user process' FPU state. If you really want + to do this, you would have to explicitly save/restore the full + FPU state (and avoid context switches). It + is generally a bad idea; use fixed point arithmetic first. + + + + + + A rigid stack limit + + + The kernel stack is about 6K in 2.2 (for most + architectures: it's about 14K on the Alpha), and shared + with interrupts so you can't use it all. Avoid deep + recursion and huge local arrays on the stack (allocate + them dynamically instead). + + + + + + The Linux kernel is portable + + + Let's keep it that way. Your code should be 64-bit clean, + and endian-independent. You should also minimize CPU + specific stuff, e.g. inline assembly should be cleanly + encapsulated and minimized to ease porting. Generally it + should be restricted to the architecture-dependent part of + the kernel tree. + + + + + + + + ioctls: Not writing a new system call + + + A system call generally looks like this + + + +asmlinkage int sys_mycall(int arg) +{ + return 0; +} + + + + First, in most cases you don't want to create a new system call. + You create a character device and implement an appropriate ioctl + for it. This is much more flexible than system calls, doesn't have + to be entered in every architecture's + include/asm/unistd.h and + arch/kernel/entry.S file, and is much more + likely to be accepted by Linus. + + + + Inside the ioctl you're in user context to a process. When a + error occurs you return a negated errno (see + include/linux/errno.h), + otherwise you return 0. + + + + After you slept you should check if a signal occurred: the + Unix/Linux way of handling signals is to temporarily exit the + system call with the -ERESTARTSYS error. The + system call entry code will switch back to user context, process + the signal handler and then your system call will be restarted + (unless the user disabled that). So you should be prepared to + process the restart, e.g. if you're in the middle of manipulating + some data structure. + + + +if (signal_pending()) + return -ERESTARTSYS; + + + + If you're doing longer computations: first think userspace. If you + really want to do it in kernel you should + regularly check if you need to give up the CPU (remember there is + cooperative multitasking per CPU). Idiom: + + + +if (current->need_resched) + schedule(); /* Will sleep */ + + + + A short note on interface design: the UNIX system call motto is + "Provide mechanism not policy". + + + + + Recipes for Deadlock + + + You cannot call any routines which may sleep, unless: + + + + + You are in user context. + + + + + + You do not own any spinlocks. + + + + + + You have interrupts enabled (actually, Andi Kleen says + that the scheduling code will enable them for you, but + that's probably not what you wanted). + + + + + + Note that some functions may sleep implicitly: common ones are + the user space access functions (*_user) and memory allocation + functions without GFP_ATOMIC. + + + + You will eventually lock up your box if you break these rules. + + + + Really. + + + + + Common Routines + + + + <function>printk()</function> + <filename class=headerfile>include/linux/kernel.h</filename> + + + + printk() feeds kernel messages to the + console, dmesg, and the syslog daemon. It is useful for debugging + and reporting errors, and can be used inside interrupt context, + but use with caution: a machine which has its console flooded with + printk messages is unusable. It uses a format string mostly + compatible with ANSI C printf, and C string concatenation to give + it a first "priority" argument: + + + +printk(KERN_INFO "i = %u\n", i); + + + + See include/linux/kernel.h; + for other KERN_ values; these are interpreted by syslog as the + level. Special case: for printing an IP address use + + + +__u32 ipaddress; +printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress)); + + + + printk() internally uses a 1K buffer and does + not catch overruns. Make sure that will be enough. + + + + + You will know when you are a real kernel hacker + when you start typoing printf as printk in your user programs :) + + + + + + + + Another sidenote: the original Unix Version 6 sources had a + comment on top of its printf function: "Printf should not be + used for chit-chat". You should follow that advice. + + + + + + + <function>copy_[to/from]_user()</function> + / + <function>get_user()</function> + / + <function>put_user()</function> + <filename class=headerfile>include/asm/uaccess.h</filename> + + + + [SLEEPS] + + + + put_user() and get_user() + are used to get and put single values (such as an int, char, or + long) from and to userspace. A pointer into userspace should + never be simply dereferenced: data should be copied using these + routines. Both return -EFAULT or 0. + + + copy_to_user() and + copy_from_user() are more general: they copy + an arbitrary amount of data to and from userspace. + + + Unlike put_user() and + get_user(), they return the amount of + uncopied data (ie. 0 still means + success). + + + [Yes, this moronic interface makes me cringe. Please submit a + patch and become my hero --RR.] + + + The functions may sleep implicitly. This should never be called + outside user context (it makes no sense), with interrupts + disabled, or a spinlock held. + + + + + <function>kmalloc()</function>/<function>kfree()</function> + <filename class=headerfile>include/linux/slab.h</filename> + + + [MAY SLEEP: SEE BELOW] + + + + These routines are used to dynamically request pointer-aligned + chunks of memory, like malloc and free do in userspace, but + kmalloc() takes an extra flag word. + Important values: + + + + + + + GFP_KERNEL + + + + + May sleep and swap to free memory. Only allowed in user + context, but is the most reliable way to allocate memory. + + + + + + + + GFP_ATOMIC + + + + + Don't sleep. Less reliable than GFP_KERNEL, + but may be called from interrupt context. You should + really have a good out-of-memory + error-handling strategy. + + + + + + + + GFP_DMA + + + + + Allocate ISA DMA lower than 16MB. If you don't know what that + is you don't need it. Very unreliable. + + + + + + + If you see a kmem_grow: Called nonatomically from int + warning message you called a memory allocation function + from interrupt context without GFP_ATOMIC. + You should really fix that. Run, don't walk. + + + + If you are allocating at least PAGE_SIZE + (include/asm/page.h) bytes, + consider using __get_free_pages() + + (include/linux/mm.h). It + takes an order argument (0 for page sized, 1 for double page, 2 + for four pages etc.) and the same memory priority flag word as + above. + + + + If you are allocating more than a page worth of bytes you can use + vmalloc(). It'll allocate virtual memory in + the kernel map. This block is not contiguous in physical memory, + but the MMU makes it look like it is for you + (so it'll only look contiguous to the CPUs, not to external device + drivers). If you really need large physically contiguous memory + for some weird device, you have a problem: it is poorly supported + in Linux because after some time memory fragmentation in a running + kernel makes it hard. The best way is to allocate the block early + in the boot process. + + + + Before inventing your own cache of often-used objects consider + using a slab cache in + include/linux/slab.h + + + + + <function>current</function> + <filename class=headerfile>include/asm/current.h</filename> + + + This global variable (really a macro) contains a pointer to + the current task structure, so is only valid in user context. + For example, when a process makes a system call, this will + point to the task structure of the calling process. It is + not NULL in interrupt context. + + + + + <function>local_irq_save()</function>/<function>local_irq_restore()</function> + <filename class=headerfile>include/asm/system.h</filename> + + + + These routines disable hard interrupts on the local CPU, and + restore them. They are reentrant; saving the previous state in + their one unsigned long flags argument. If you + know that interrupts are enabled, you can simply use + local_irq_disable() and + local_irq_enable(). + + + + + <function>local_bh_disable()</function>/<function>local_bh_enable()</function> + <filename class=headerfile>include/asm/softirq.h</filename> + + + These routines disable soft interrupts on the local CPU, and + restore them. They are reentrant; if soft interrupts were + disabled before, they will still be disabled after this pair + of functions has been called. They prevent softirqs, tasklets + and bottom halves from running on the current CPU. + + + + + <function>smp_processor_id</function>()/<function>cpu_[number/logical]_map()</function> + <filename class=headerfile>include/asm/smp.h</filename> + + + smp_processor_id() returns the current + processor number, between 0 and NR_CPUS (the + maximum number of CPUs supported by Linux, currently 32). These + values are not necessarily continuous: to get a number between 0 + and smp_num_cpus() (the number of actual + processors in this machine), the + cpu_number_map() function is used to map the + processor id to a logical number. + cpu_logical_map() does the reverse. + + + + + <type>__init</type>/<type>__exit</type>/<type>__initdata</type> + <filename class=headerfile>include/linux/init.h</filename> + + + After boot, the kernel frees up a special section; functions + marked with __init and data structures marked with + __initdata are dropped after boot is complete (within + modules this directive is currently ignored). __exit + is used to declare a function which is only required on exit: the + function will be dropped if this file is not compiled as a module. + See the header file for use. + + + + + + <function>__initcall()</function>/<function>module_init()</function> + <filename class=headerfile>include/linux/init.h</filename> + + Many parts of the kernel are well served as a module + (dynamically-loadable parts of the kernel). Using the + module_init() and + module_exit() macros it is easy to write code + without #ifdefs which can operate both as a module or built into + the kernel. + + + + The module_init() macro defines which + function is to be called at module insertion time (if the file is + compiled as a module), or at boot time: if the file is not + compiled as a module the module_init() macro + becomes equivalent to __initcall(), which + through linker magic ensures that the function is called on boot. + + + + The function can return a negative error number to cause + module loading to fail (unfortunately, this has no effect if + the module is compiled into the kernel). For modules, this is + called in user context, with interrupts enabled, and the + kernel lock held, so it can sleep. + + + + + <function>module_exit()</function> + <filename class=headerfile>include/linux/init.h</filename> + + + This macro defines the function to be called at module removal + time (or never, in the case of the file compiled into the + kernel). It will only be called if the module usage count has + reached zero. This function can also sleep, but cannot fail: + everything must be cleaned up by the time it returns. + + + + + <function>MOD_INC_USE_COUNT</function>/<function>MOD_DEC_USE_COUNT</function> + <filename class=headerfile>include/linux/module.h</filename> + + + These manipulate the module usage count, to protect against + removal (a module also can't be removed if another module uses + one of its exported symbols: see below). Every reference to + the module from user context should be reflected by this + counter (e.g. for every data structure or socket) before the + function sleeps. To quote Tim Waugh: + + + +/* THIS IS BAD */ +foo_open (...) +{ + stuff.. + if (fail) + return -EBUSY; + sleep.. (might get unloaded here) + stuff.. + MOD_INC_USE_COUNT; + return 0; +} + +/* THIS IS GOOD / +foo_open (...) +{ + MOD_INC_USE_COUNT; + stuff.. + if (fail) { + MOD_DEC_USE_COUNT; + return -EBUSY; + } + sleep.. (safe now) + stuff.. + return 0; +} + + + + + + Wait Queues + <filename class=headerfile>include/linux/wait.h</filename> + + + [SLEEPS] + + + + A wait queue is used to wait for someone to wake you up when a + certain condition is true. They must be used carefully to ensure + there is no race condition. You declare a + wait_queue_head_t, and then processes which want to + wait for that condition declare a wait_queue_t + referring to themselves, and place that in the queue. + + + + Declaring + + + You declare a wait_queue_head_t using the + DECLARE_WAIT_QUEUE_HEAD() macro, or using the + init_waitqueue_head() routine in your + initialization code. + + + + + Queuing + + + Placing yourself in the waitqueue is fairly complex, because you + must put yourself in the queue before checking the condition. + There is a macro to do this: + wait_event_interruptible() + + include/linux/sched.h The + first argument is the wait queue head, and the second is an + expression which is evaluated; the macro returns + 0 when this expression is true, or + -ERESTARTSYS if a signal is received. + The wait_event() version ignores signals. + + + + + Waking Up Queued Tasks + + + Call wake_up() + + include/linux/sched.h;, + which will wake up every process in the queue. The exception is + if one has TASK_EXCLUSIVE set, in which case + the remainder of the queue will not be woken. + + + + + + Atomic Operations + + + Certain operations are guaranteed atomic on all platforms. The + first class of operations work on atomic_t + + include/asm/atomic.h; this + contains a signed integer (at least 32 bits long), and you must use + these functions to manipulate or read atomic_t variables. + atomic_read() and + atomic_set() get and set the counter, + atomic_add(), + atomic_sub(), + atomic_inc(), + atomic_dec(), and + atomic_dec_and_test() (returns + true if it was decremented to zero). + + + + Yes. It returns true (i.e. != 0) if the + atomic variable is zero. + + + + Note that these functions are slower than normal arithmetic, and + so should not be used unnecessarily. On some platforms they + are much slower, like 32-bit Sparc where they use a spinlock. + + + + The second class of atomic operations is atomic bit operations, + defined in + + include/asm/bitops.h. These + operations generally take a pointer to the bit pattern, and a bit + number: 0 is the least significant bit. + set_bit(), clear_bit() + and change_bit() set, clear, and flip the + given bit. test_and_set_bit(), + test_and_clear_bit() and + test_and_change_bit() do the same thing, + except return true if the bit was previously set; these are + particularly useful for very simple locking. + + + + It is possible to call these operations with bit indices greater + than 31. The resulting behavior is strange on big-endian + platforms though so it is a good idea not to do this. + + + + + Symbols + + + Within the kernel proper, the normal linking rules apply + (ie. unless a symbol is declared to be file scope with the + static keyword, it can be used anywhere in the + kernel). However, for modules, a special exported symbol table is + kept which limits the entry points to the kernel proper. Modules + can also export symbols. + + + + <function>EXPORT_SYMBOL()</function> + <filename class=headerfile>include/linux/module.h</filename> + + + This is the classic method of exporting a symbol, and it works + for both modules and non-modules. In the kernel all these + declarations are often bundled into a single file to help + genksyms (which searches source files for these declarations). + See the comment on genksyms and Makefiles below. + + + + + <function>EXPORT_SYMTAB</function> + + + For convenience, a module usually exports all non-file-scope + symbols (ie. all those not declared static). If this + is defined before + + include/linux/module.h is + included, then only symbols explicit exported with + EXPORT_SYMBOL() will be exported. + + + + + + Routines and Conventions + + + Double-linked lists + <filename class=headerfile>include/linux/list.h</filename> + + + There are three sets of linked-list routines in the kernel + headers, but this one seems to be winning out (and Linus has + used it). If you don't have some particular pressing need for + a single list, it's a good choice. In fact, I don't care + whether it's a good choice or not, just use it so we can get + rid of the others. + + + + + Return Conventions + + + For code called in user context, it's very common to defy C + convention, and return 0 for success, + and a negative error number + (eg. -EFAULT) for failure. This can be + unintuitive at first, but it's fairly widespread in the networking + code, for example. + + + + The filesystem code uses ERR_PTR() + + include/linux/fs.h; to + encode a negative error number into a pointer, and + IS_ERR() and PTR_ERR() + to get it back out again: avoids a separate pointer parameter for + the error number. Icky, but in a good way. + + + + + Breaking Compilation + + + Linus and the other developers sometimes change function or + structure names in development kernels; this is not done just to + keep everyone on their toes: it reflects a fundamental change + (eg. can no longer be called with interrupts on, or does extra + checks, or doesn't do checks which were caught before). Usually + this is accompanied by a fairly complete note to the linux-kernel + mailing list; search the archive. Simply doing a global replace + on the file usually makes things worse. + + + + + Initializing structure members + + + The preferred method of initializing structures is to use the + gcc Labeled Elements extension, eg: + + +static struct block_device_operations opt_fops = { + open: opt_open, + release: opt_release, + ioctl: opt_ioctl, + check_media_change: opt_media_change, +}; + + + + This makes it easy to grep for, and makes it clear which + structure fields are set. You should do this because it looks + cool. + + + + + GNU Extensions + + + GNU Extensions are explicitly allowed in the Linux kernel. + Note that some of the more complex ones are not very well + supported, due to lack of general use, but the following are + considered standard (see the GCC info page section "C + Extensions" for more details - Yes, really the info page, the + man page is only a short summary of the stuff in info): + + + + + Inline functions + + + + + Statement expressions (ie. the ({ and }) constructs). + + + + + Declaring attributes of a function / variable / type + (__attribute__) + + + + + Labeled elements + + + + + typeof + + + + + Zero length arrays + + + + + Macro varargs + + + + + Arithmetic on void pointers + + + + + Non-Constant initializers + + + + + Assembler Instructions (not outside arch/ and include/asm/) + + + + + Function names as strings (__FUNCTION__) + + + + + __builtin_constant_p() + + + + + + Be wary when using long long in the kernel, the code gcc generates for + it is horrible and worse: division and multiplication does not work + on i386 because the GCC runtime functions for it are missing from + the kernel environment. + + + + + + + C++ + + + Using C++ in the kernel is usually a bad idea, because the + kernel does not provide the necessary runtime environment + and the include files are not tested for it. It is still + possible, but not recommended. If you really want to do + this, forget about exceptions at least. + + + + + #if + + + It is generally considered cleaner to use macros in header files + (or at the top of .c files) to abstract away functions rather than + using `#if' pre-processor statements throughout the source code. + + + + + + Putting Your Stuff in the Kernel + + + In order to get your stuff into shape for official inclusion, or + even to make a neat patch, there's administrative work to be + done: + + + + + Figure out whose pond you've been pissing in. Look at the top of + the source files, inside the MAINTAINERS + file, and last of all in the CREDITS file. + You should coordinate with this person to make sure you're not + duplicating effort, or trying something that's already been + rejected. + + + + Make sure you put your name and EMail address at the top of + any files you create or mangle significantly. This is the + first place people will look when they find a bug, or when + they want to make a change. + + + + + + Usually you want a configuration option for your kernel hack. + Edit Config.in in the appropriate directory + (but under arch/ it's called + config.in). The Config Language used is not + bash, even though it looks like bash; the safe way is to use only + the constructs that you already see in + Config.in files (see + Documentation/kbuild/config-language.txt). + It's good to run "make xconfig" at least once to test (because + it's the only one with a static parser). + + + + Variables which can be Y or N use bool followed by a + tagline and the config define name (which must start with + CONFIG_). The tristate function is the same, but + allows the answer M (which defines + CONFIG_foo_MODULE in your source, instead of + CONFIG_FOO) if CONFIG_MODULES + is enabled. + + + + You may well want to make your CONFIG option only visible if + CONFIG_EXPERIMENTAL is enabled: this serves as a + warning to users. There many other fancy things you can do: see + the the various Config.in files for ideas. + + + + + + Edit the Makefile: the CONFIG variables are + exported here so you can conditionalize compilation with `ifeq'. + If your file exports symbols then add the names to + MX_OBJS or OX_OBJS instead + of M_OBJS or O_OBJS, so + that genksyms will find them. + + + + + + Document your option in Documentation/Configure.help. Mention + incompatibilities and issues here. Definitely + end your description with if in doubt, say N + (or, occasionally, `Y'); this is for people who have no + idea what you are talking about. + + + + + + Put yourself in CREDITS if you've done + something noteworthy, usually beyond a single file (your name + should be at the top of the source files anyway). + MAINTAINERS means you want to be consulted + when changes are made to a subsystem, and hear about bugs; it + implies a more-than-passing commitment to some part of the code. + + + + + + + Kernel Cantrips + + + Some favorites from browsing the source. Feel free to add to this + list. + + + + include/linux/brlock.h: + + +extern inline void br_read_lock (enum brlock_indices idx) +{ + /* + * This causes a link-time bug message if an + * invalid index is used: + */ + if (idx >= __BR_END) + __br_lock_usage_bug(); + + read_lock(&__brlock_array[smp_processor_id()][idx]); +} + + + + include/linux/fs.h: + + +/* + * Kernel pointers have redundant information, so we can use a + * scheme where we can return either an error code or a dentry + * pointer with the same return value. + * + * This should be a per-architecture thing, to allow different + * error and pointer decisions. + */ + #define ERR_PTR(err) ((void *)((long)(err))) + #define PTR_ERR(ptr) ((long)(ptr)) + #define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000)) + + + + include/asm-i386/uaccess.h: + + + +#define copy_to_user(to,from,n) \ + (__builtin_constant_p(n) ? \ + __constant_copy_to_user((to),(from),(n)) : \ + __generic_copy_to_user((to),(from),(n))) + + + + arch/sparc/kernel/head.S: + + + +/* + * Sun people can't spell worth damn. "compatability" indeed. + * At least we *know* we can't spell, and use a spell-checker. + */ + +/* Uh, actually Linus it is I who cannot spell. Too much murky + * Sparc assembly will do this to ya. + */ +C_LABEL(cputypvar): + .asciz "compatability" + +/* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */ + .align 4 +C_LABEL(cputypvar_sun4m): + .asciz "compatible" + + + + arch/sparc/lib/checksum.S: + + + + /* Sun, you just can't beat me, you just can't. Stop trying, + * give up. I'm serious, I am going to kick the living shit + * out of you, game over, lights out. + */ + + + + + Thanks + + + Thanks to Andi Kleen for the idea, answering my questions, fixing + my mistakes, filling content, etc. Philipp Rumpf for more spelling + and clarity fixes, and some excellent non-obvious points. Werner + Almesberger for giving me a great summary of + disable_irq(), and Jes Sorensen and Andrea + Arcangeli added caveats. Michael Elizabeth Chastain for checking + and adding to the Configure section. Telsa Gwynne for teaching me DocBook. + + +
+ diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/DocBook/kernel-locking.tmpl linux/Documentation/DocBook/kernel-locking.tmpl --- v2.3.99-pre8/linux/Documentation/DocBook/kernel-locking.tmpl Wed Dec 31 16:00:00 1969 +++ linux/Documentation/DocBook/kernel-locking.tmpl Sun May 21 20:18:07 2000 @@ -0,0 +1,1221 @@ + + + + + Unreliable Guide To Locking + + + + Paul + Rusty + Russell + +
+ rusty@linuxcare.com +
+
+
+
+ + + 2000 + Paul Russell + + + + + This documentation 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 (at your option) any later + version. + + + + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + +
+ + + + Introduction + + Welcome, to Rusty's Remarkably Unreliable Guide to Kernel + Locking issues. This document describes the locking systems in + the Linux Kernel as we approach 2.4. + + + It looks like SMP + is here to stay; so everyone hacking on the kernel + these days needs to know the fundamentals of concurrency and locking + for SMP. + + + + The Problem With Concurrency + + (Skip this if you know what a Race Condition is). + + + In a normal program, you can increment a counter like so: + + + very_important_count++; + + + + This is what they would expect to happen: + + + + Expected Results + + + + + + Instance 1 + Instance 2 + + + + + + read very_important_count (5) + + + + add 1 (6) + + + + write very_important_count (6) + + + + + read very_important_count (6) + + + + add 1 (7) + + + + write very_important_count (7) + + + + +
+ + + This is what might happen: + + + + Possible Results + + + + + Instance 1 + Instance 2 + + + + + + read very_important_count (5) + + + + + read very_important_count (5) + + + add 1 (6) + + + + + add 1 (5) + + + write very_important_count (6) + + + + + write very_important_count (6) + + + +
+ + + This overlap, where what actually happens depends on the + relative timing of multiple tasks, is called a race condition. + The piece of code containing the concurrency issue is called a + critical region. And especially since Linux starting running + on SMP machines, they became one of the major issues in kernel + design and implementation. + + + The solution is to recognize when these simultaneous accesses + occur, and use locks to make sure that only one instance can + enter the critical region at any time. There are many + friendly primitives in the Linux kernel to help you do this. + And then there are the unfriendly primitives, but I'll pretend + they don't exist. + +
+
+ + + Two Main Types of Kernel Locks: Spinlocks and Semaphores + + + There are two main types of kernel locks. The fundamental type + is the spinlock + (include/asm/spinlock.h), + which is a very simple single-holder lock: if you can't get the + spinlock, you keep trying (spinning) until you can. Spinlocks are + very small and fast, and can be used anywhere. + + + The second type is a semaphore + (include/asm/semaphore.h): it + can have more than one holder at any time (the number decided at + initialization time), although it is most commonly used as a + single-holder lock (a mutex). If you can't get a semaphore, + your task will put itself on the queue, and be woken up when the + semaphore is released. This means the CPU will do something + else while you are waiting, but there are many cases when you + simply can't sleep, and so have to use a spinlock instead. + + + + Locks and Uniprocessor Kernels + + + For kernels compiled without CONFIG_SMP, spinlocks + do not exist at all. This is an excellent design decision: when + no-one else can run at the same time, there is no reason to + have a lock at all. + + + + You should always test your locking code with CONFIG_SMP + enabled, even if you don't have an SMP test box, because it + will still catch some (simple) kinds of deadlock. + + + + Semaphores still exist, because they are required for + synchronization between user + contexts, as we will see below. + + + + + Read/Write Lock Variants + + + Both spinlocks and semaphores have read/write variants: + rwlock_t and struct rw_semaphore. + These divide users into two classes: the readers and the writers. If + you are only reading the data, you can get a read lock, but to write to + the data you need the write lock. Many people can hold a read lock, + but a writer must be sole holder. + + + + This means much smoother locking if your code divides up + neatly along reader/writer lines. All the discussions below + also apply to read/write variants. + + + + + Locking Only In User Context + + + If you have a data structure which is only ever accessed from + user context, then you can use a simple semaphore + (linux/asm/semaphore.h) to protect it. This + is the most trivial case: you initialize the semaphore to the number + of resources available (usually 1), and call + down_interruptible() to grab the semaphore, and + up() to release it. There is also a + down(), which should be avoided, because it + will not return if a signal is received. + + + + Example: linux/net/core/netfilter.c allows + registration of new setsockopt() and + getsockopt() calls, with + nf_register_sockopt(). Registration and + de-registration are only done on module load and unload (and boot + time, where there is no concurrency), and the list of registrations + is only consulted for an unknown setsockopt() + or getsockopt() system call. The + nf_sockopt_mutex is perfect to protect this, + especially since the setsockopt and getsockopt calls may well + sleep. + + + + + Locking Between User Context and BHs + + + If a bottom half shares + data with user context, you have two problems. Firstly, the current + user context can be interrupted by a bottom half, and secondly, the + critical region could be entered from another CPU. This is where + spin_lock_bh() + (include/linux/spinlock.h) is + used. It disables bottom halves on that CPU, then grabs the lock. + spin_unlock_bh() does the reverse. + + + + This works perfectly for UP + as well: the spin lock vanishes, and this macro + simply becomes local_bh_disable() + (include/asm/softirq.h), which + protects you from the bottom half being run. + + + + + Locking Between User Context and Tasklets/Soft IRQs + + + This is exactly the same as above, because + local_bh_disable() actually disables all + softirqs and tasklets + on that CPU as well. It should really be + called `local_softirq_disable()', but the name has been preserved + for historical reasons. Similarly, + spin_lock_bh() would now be called + spin_lock_softirq() in a perfect world. + + + + + Locking Between Bottom Halves + + + Sometimes a bottom half might want to share data with + another bottom half (especially remember that timers are run + off a bottom half). + + + + The Same BH + + + Since a bottom half is never run on two CPUs at once, you + don't need to worry about your bottom half being run twice + at once, even on SMP. + + + + + Different BHs + + + Since only one bottom half ever runs at a time once, you + don't need to worry about race conditions with other bottom + halves. Beware that things might change under you, however, + if someone changes your bottom half to a tasklet. If you + want to make your code future-proof, pretend you're already + running from a tasklet (see below), and doing the extra + locking. Of course, if it's five years before that happens, + you're gonna look like a damn fool. + + + + + + Locking Between Tasklets + + + Sometimes a tasklet might want to share data with another + tasklet, or a bottom half. + + + + The Same Tasklet + + Since a tasklet is never run on two CPUs at once, you don't + need to worry about your tasklet being reentrant (running + twice at once), even on SMP. + + + + + Different Tasklets + + If another tasklet (or bottom half, such as a timer) wants + to share data with your tasklet, you will both need to use + spin_lock() and + spin_unlock() calls. + spin_lock_bh() is + unnecessary here, as you are already in a a tasklet, and + none will be run on the same CPU. + + + + + + Locking Between Softirqs + + + Often a softirq might + want to share data with itself, a tasklet, or a bottom half. + + + + The Same Softirq + + + The same softirq can run on the other CPUs: you can use a + per-CPU array (see ) for better + performance. If you're going so far as to use a softirq, + you probably care about scalable performance enough + to justify the extra complexity. + + + + You'll need to use spin_lock() and + spin_unlock() for shared data. + + + + + Different Softirqs + + + You'll need to use spin_lock() and + spin_unlock() for shared data, whether it + be a timer (which can be running on a different CPU), bottom half, + tasklet or the same or another softirq. + + + + + + + Hard IRQ Context + + + Hardware interrupts usually communicate with a bottom half, + tasklet or softirq. Frequently this involved putting work in a + queue, which the BH/softirq will take out. + + + + Locking Between Hard IRQ and Softirqs/Tasklets/BHs + + + If a hardware irq handler shares data with a softirq, you have + two concerns. Firstly, the softirq processing can be + interrupted by a hardware interrupt, and secondly, the + critical region could be entered by a hardware interrupt on + another CPU. This is where spin_lock_irq() is + used. It is defined to disable interrupts on that cpu, then grab + the lock. spin_unlock_irq() does the reverse. + + + + This works perfectly for UP as well: the spin lock vanishes, + and this macro simply becomes local_irq_disable() + (include/asm/smp.h), which + protects you from the softirq/tasklet/BH being run. + + + + spin_lock_irqsave() + (include/linux/spinlock.h) is a variant + which saves whether interrupts were on or off in a flags word, + which is passed to spin_lock_irqrestore(). This + means that the same code can be used inside an hard irq handler (where + interrupts are already off) and in softirqs (where the irq + disabling is required). + + + + + + Common Techniques + + + This section lists some common dilemmas and the standard + solutions used in the Linux kernel code. If you use these, + people will find your code simpler to understand. + + + + If I could give you one piece of advice: never sleep with anyone + crazier than yourself. But if I had to give you advice on + locking: keep it simple. + + + + Lock data, not code. + + + + Be reluctant to introduce new locks. + + + + Strangely enough, this is the exact reverse of my advice when + you have slept with someone crazier than yourself. + + + + No Writers in Interrupt Context + + + There is a fairly common case where an interrupt handler needs + access to a critical region, but does not need write access. + In this case, you do not need to use + read_lock_irq(), but only + read_lock() everywhere (since if an interrupt + occurs, the irq handler will only try to grab a read lock, which + won't deadlock). You will still need to use + write_lock_irq(). + + + + Similar logic applies to locking between softirqs/tasklets/BHs + which never need a write lock, and user context: + read_lock() and + write_lock_bh(). + + + + + Deadlock: Simple and Advanced + + + There is a coding bug where a piece of code tries to grab a + spinlock twice: it will spin forever, waiting for the lock to + be released (spinlocks and writelocks are not re-entrant in + Linux). This is trivial to diagnose: not a + stay-up-five-nights-talk-to-fluffy-code-bunnies kind of + problem. + + + + For a slightly more complex case, imagine you have a region + shared by a bottom half and user context. If you use a + spin_lock() call to protect it, it is + possible that the user context will be interrupted by the bottom + half while it holds the lock, and the bottom half will then spin + forever trying to get the same lock. + + + + Both of these are called deadlock, and as shown above, it can + occur even with a single CPU (although not on UP compiles, + since spinlocks vanish on kernel compiles with + CONFIG_SMP=n. You'll still get data corruption + in the second example). + + + + This complete lockup is easy to diagnose: on SMP boxes the + watchdog timer or compiling with DEBUG_SPINLOCKS set + (include/linux/spinlock.h) will show this up + immediately when it happens. + + + + A more complex problem is the so-called `deadly embrace', + involving two or more locks. Say you have a hash table: each + entry in the table is a spinlock, and a chain of hashed + objects. Inside a softirq handler, you sometimes want to + alter an object from one place in the hash to another: you + grab the spinlock of the old hash chain and the spinlock of + the new hash chain, and delete the object from the old one, + and insert it in the new one. + + + + There are two problems here. First, if your code ever + tries to move the object to the same chain, it will deadlock + with itself as it tries to lock it twice. Secondly, if the + same softirq on another CPU is trying to move another object + in the reverse direction, the following could happen: + + + + Consequences + + + + + + CPU 1 + CPU 2 + + + + + + Grab lock A -> OK + Grab lock B -> OK + + + Grab lock B -> spin + Grab lock A -> spin + + + +
+ + + The two CPUs will spin forever, waiting for the other to give up + their lock. It will look, smell, and feel like a crash. + + + + Preventing Deadlock + + + Textbooks will tell you that if you always lock in the same + order, you will never get this kind of deadlock. Practice + will tell you that this approach doesn't scale: when I + create a new lock, I don't understand enough of the kernel + to figure out where in the 5000 lock hierarchy it will fit. + + + + The best locks are encapsulated: they never get exposed in + headers, and are never held around calls to non-trivial + functions outside the same file. You can read through this + code and see that it will never deadlock, because it never + tries to grab another lock while it has that one. People + using your code don't even need to know you are using a + lock. + + + + A classic problem here is when you provide callbacks or + hooks: if you call these with the lock held, you risk simple + deadlock, or a deadly embrace (who knows what the callback + will do?). Remember, the other programmers are out to get + you, so don't do this. + + + + + Overzealous Prevention Of Deadlocks + + + Deadlocks are problematic, but not as bad as data + corruption. Code which grabs a read lock, searches a list, + fails to find what it wants, drops the read lock, grabs a + write lock and inserts the object has a race condition. + + + + If you don't see why, please stay the fuck away from my code. + + +
+ + + Per-CPU Data + + + A great technique for avoiding locking which is used fairly + widely is to duplicate information for each CPU. For example, + if you wanted to keep a count of a common condition, you could + use a spin lock and a single counter. Nice and simple. + + + + If that was too slow [it's probably not], you could instead + use a counter for each CPU [don't], then none of them need an + exclusive lock [you're wasting your time here]. To make sure + the CPUs don't have to synchronize caches all the time, align + the counters to cache boundaries by appending + `__cacheline_aligned' to the declaration + (include/linux/cache.h). + [Can't you think of anything better to do?] + + + + They will need a read lock to access their own counters, + however. That way you can use a write lock to grant exclusive + access to all of them at once, to tally them up. + + + + + Big Reader Locks + + + A classic example of per-CPU information is Ingo's `big + reader' locks + (linux/include/brlock.h). These + use the Per-CPU Data techniques described above to create a lock which + is very fast to get a read lock, but agonizingly slow for a write + lock. + + + + Fortunately, there are a limited number of these locks + available: you have to go through a strict interview process + to get one. + + + + + Avoiding Locks: Read And Write Ordering + + + Sometimes it is possible to avoid locking. Consider the + following case from the 2.2 firewall code, which inserted an + element into a single linked list in user context: + + + + new->next = i->next; + i->next = new; + + + + Here the author (Alan Cox, who knows what he's doing) assumes + that the pointer assignments are atomic. This is important, + because networking packets would traverse this list on bottom + halves without a lock. Depending on their exact timing, they + would either see the new element in the list with a valid + next pointer, or it would not be in the + list yet. + + + + Of course, the writes must be in this + order, otherwise the new element appears in the list with an + invalid next pointer, and any other + CPU iterating at the wrong time will jump through it into garbage. + Because modern CPUs reorder, Alan's code actually read as follows: + + + + new->next = i->next; + wmb(); + i->next = new; + + + + The wmb() is a write memory barrier + (include/asm/system.h): neither + the compiler nor the CPU will allow any writes to memory after the + wmb() to be visible to other hardware + before any of the writes before the wmb(). + + + + As i386 does not do write reordering, this bug would never + show up on that platform. On other SMP platforms, however, it + will. + + + + There is also rmb() for read ordering: to ensure + any previous variable reads occur before following reads. The simple + mb() macro combines both + rmb() and wmb(). + + + + Dropping or gaining a spinlock, and any atomic operation are + all defined to act as memory barriers (ie. as per the + mb() macro). + + + + There is a similar, but unrelated, problem with code like the + following: + + + + if (!(ctrack->status & IPS_CONFIRMED)) { + spin_lock_bh(&ip_conntrack_lock); + if (!(ctrack->status & IPS_CONFIRMED)) { + clean_from_lists(h->ctrack); + h->ctrack->status |= IPS_CONFIRMED; + } + spin_unlock_bh(&ip_conntrack_lock); + } + + + + In this case, the author has tried to be tricky: knowing that + the CONFIRMED bit is set and never reset in the status word, + you can test it outside the lock, and frequently avoid + grabbing the lock at all. However, the compiler could cache + the value in a register, rather than rereading it once the + lock is obtained, creating a subtle race. The way to get + around this is to declare the status field `volatile', or use + a temporary volatile pointer to achieve the same effect in + this one place. + + + + + Avoiding Locks: Atomic Operations + + + There are a number of atomic operations defined in + include/asm/atomic.h: these + are guaranteed to be seen atomically from all CPUs in the system, thus + avoiding races. If your shared data consists of a single counter, say, + these operations might be simpler than using spinlocks (although for + anything non-trivial using spinlocks is clearer). + + + + Note that the atomic operations are defined to act as both + read and write barriers on all platforms. + + + + + Protecting A Collection of Objects: Reference Counts + + + Locking a collection of objects is fairly easy: you get a + single spinlock, and you make sure you grab it before + searching, adding or deleting an object. + + + + The purpose of this lock is not to protect the individual + objects: you might have a separate lock inside each one for + that. It is to protect the data structure + containing the objects from race conditions. Often + the same lock is used to protect the contents of all the + objects as well, for simplicity, but they are inherently + orthogonal (and many other big words designed to confuse). + + + + Changing this to a read-write lock will often help markedly if + reads are far more common that writes. If not, there is + another approach you can use to reduce the time the lock is + held: reference counts. + + + + In this approach, an object has an owner, who sets the + reference count to one. Whenever you get a pointer to the + object, you increment the reference count (a `get' operation). + Whenever you relinquish a pointer, you decrement the reference + count (a `put' operation). When the owner wants to destroy + it, they mark it dead, and do a put. + + + + Whoever drops the reference count to zero (usually implemented + with atomic_dec_and_test()) actually cleans + up and frees the object. + + + + This means that you are guaranteed that the object won't + vanish underneath you, even though you no longer have a lock + for the collection. + + + + Here's some skeleton code: + + + + void create_foo(struct foo *x) + { + atomic_set(&x->use, 1); + spin_lock_bh(&list_lock); + ... insert in list ... + spin_unlock_bh(&list_lock); + } + + struct foo *get_foo(int desc) + { + struct foo *ret; + + spin_lock_bh(&list_lock); + ... find in list ... + if (ret) atomic_inc(&ret->use); + spin_unlock_bh(&list_lock); + + return ret; + } + + void put_foo(struct foo *x) + { + if (atomic_dec_and_test(&x->use)) + kfree(foo); + } + + void destroy_foo(struct foo *x) + { + spin_lock_bh(&list_lock); + ... remove from list ... + spin_unlock_bh(&list_lock); + + put_foo(x); + } + + + + Macros To Help You + + There are a set of debugging macros tucked inside + include/linux/netfilter_ipv4/lockhelp.h + and listhelp.h: these are very + useful for ensuring that locks are held in the right places to protect + infrastructure. + + + + + + Things Which Sleep + + + You can never call the following routines while holding a + spinlock, as they may sleep: + + + + + + Accesses to + userspace: + + + + + copy_from_user() + + + + + copy_to_user() + + + + + get_user() + + + + + put_user() + + + + + + + + kmalloc(GFP_KERNEL) + + + + + + printk(), which can be called from + user context, interestingly enough. + + + + + + + The Fucked Up Sparc + + + Alan Cox says the irq disable/enable is in the register + window on a sparc. Andi Kleen says when you do + restore_flags in a different function you mess up all the + register windows. + + + + So never pass the flags word set by + spin_lock_irqsave() and brethren to another + function (unless it's declared inline. Usually no-one + does this, but now you've been warned. Dave Miller can never do + anything in a straightforward manner (I can say that, because I have + pictures of him and a certain PowerPC maintainer in a compromising + position). + + + + + Racing Timers: A Kernel Pastime + + + Timers can produce their own special problems with races. + Consider a collection of objects (list, hash, etc) where each + object has a timer which is due to destroy it. + + + + If you want to destroy the entire collection (say on module + removal), you might do the following: + + + + /* THIS CODE BAD BAD BAD BAD: IF IT WAS ANY WORSE IT WOULD USE + HUNGARIAN NOTATION */ + spin_lock_bh(&list_lock); + + while (list) { + struct foo *next = list->next; + del_timer(&list->timer); + kfree(list); + list = next; + } + + spin_unlock_bh(&list_lock); + + + + Sooner or later, this will crash on SMP, because a timer can + have just gone off before the spin_lock_bh(), + and it will only get the lock after we + spin_unlock_bh(), and then try to free + the element (which has already been freed!). + + + + This can be avoided by checking the result of + del_timer(): if it returns + 1, the timer has been deleted. + If 0, it means (in this + case) that it is currently running, so we can do: + + + + retry: + spin_lock_bh(&list_lock); + + while (list) { + struct foo *next = list->next; + if (!del_timer(&list->timer)) { + /* Give timer a chance to delete this */ + spin_unlock_bh(&list_lock); + goto retry; + } + kfree(list); + list = next; + } + + spin_unlock_bh(&list_lock); + + + + Another common problem is deleting timers which restart + themselves (by calling add_timer() at the end + of their timer function). Because this is a fairly common case + which is prone to races, the function del_timer_sync() + (include/linux/timer.h) is + provided to handle this case. It returns the number of times the timer + had to be deleted before we finally stopped it from adding itself back + in. + + +
+ + + Further reading + + + + + Documentation/spinlocks.txt: + Linus Torvalds' spinlocking tutorial in the kernel sources. + + + + + + Unix Systems for Modern Architectures: Symmetric + Multiprocessing and Caching for Kernel Programmers: + + + + Curt Schimmel's very good introduction to kernel level + locking (not written for Linux, but nearly everything + applies). The book is expensive, but really worth every + penny to understand SMP locking. [ISBN: 0201633388] + + + + + + + Thanks + + + Thanks to Telsa Gwynne for DocBooking, neatening and adding + style. + + + + Thanks to Martin Pool, Philipp Rumpf, Stephen Rothwell, Paul + Mackerras, Ruedi Aschwanden, Alan Cox for proofreading, + correcting, flaming, commenting. + + + + Thanks to the cabal for having no influence on this document. + + + + + Glossary + + + bh + + + Bottom Half: for historical reasons, functions with + `_bh' in them often now refer to any software interrupt, e.g. + spin_lock_bh() blocks any software interrupt + on the current CPU. Bottom halves are deprecated, and will + eventually be replaced by tasklets. Only one bottom half will be + running at any time. + + + + + + Hardware Interrupt / Hardware IRQ + + + Hardware interrupt request. in_irq() returns + true in a hardware interrupt handler (it + also returns true when interrupts are blocked). + + + + + + Interrupt Context + + + Not user context: processing a hardware irq or software irq. + Indicated by the in_interrupt() macro + returning true (although it also + returns true when interrupts or BHs are blocked). + + + + + + SMP + + + Symmetric Multi-Processor: kernels compiled for multiple-CPU + machines. (CONFIG_SMP=y). + + + + + + softirq + + + Strictly speaking, one of up to 32 enumerated software + interrupts which can run on multiple CPUs at once. + Sometimes used to refer to tasklets and bottom halves as + well (ie. all software interrupts). + + + + + + Software Interrupt / Software IRQ + + + Software interrupt handler. in_irq() returns + false; in_softirq() + returns true. Tasklets, softirqs and + bottom halves all fall into the category of `software interrupts'. + + + + + + tasklet + + + A dynamically-registrable software interrupt, + which is guaranteed to only run on one CPU at a time. + + + + + + UP + + + Uni-Processor: Non-SMP. (CONFIG_SMP=n). + + + + + + User Context + + + The kernel executing on behalf of a particular + process or kernel thread (given by the current() + macro.) Not to be confused with userspace. Can be interrupted by + software or hardware interrupts. + + + + + + Userspace + + + A process executing its own code outside the kernel. + + + + + +
+ diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/DocBook/parportbook.tmpl linux/Documentation/DocBook/parportbook.tmpl --- v2.3.99-pre8/linux/Documentation/DocBook/parportbook.tmpl Tue Apr 11 15:09:11 2000 +++ linux/Documentation/DocBook/parportbook.tmpl Tue May 23 08:44:35 2000 @@ -1,8 +1,9 @@ + - The Parallel Port Subsystem + The Linux 2.4 Parallel Port Subsystem @@ -51,90 +52,97 @@ - + - -Design goals + + Design goals - -The problems + + The problems - - - - + + The first parallel port support for Linux came with the line + printer driver, lp. The printer driver is a + character special device, and (in Linux 2.0) had support for + writing, via write, and configuration and + statistics reporting via ioctl. + + + + The printer driver could be used on any computer that had an IBM + PC-compatible parallel port. Because some architectures have + parallel ports that aren't really the same as PC-style ports, + other variants of the printer driver were written in order to + support Amiga and Atari parallel ports. + + + + When the Iomega Zip drive was released, and a driver written for + it, a problem became apparent. The Zip drive is a parallel port + device that provides a parallel port of its own---it is designed + to sit between a computer and an attached printer, with the + printer plugged into the Zip drive, and the Zip drive plugged into + the computer. + + + + The problem was that, although printers and Zip drives were both + supported, for any given port only one could be used at a time. + Only one of the two drivers could be present in the kernel at + once. This was because of the fact that both drivers wanted to + drive the same hardware---the parallel port. When the printer + driver initialised, it would call the + check_region function to make sure that the + IO region associated with the parallel port was free, and then it + would call request_region to allocate it. + The Zip drive used the same mechanism. Whichever driver + initialised first would gain exclusive control of the parallel + port. + + + + The only way around this problem at the time was to make sure that + both drivers were available as loadable kernel modules. To use + the printer, load the printer driver module; then for the Zip + drive, unload the printer driver module and load the Zip driver + module. + + + + The net effect was that printing a document that was stored on a + Zip drive was a bit of an ordeal, at least if the Zip drive and + printer shared a parallel port. A better solution was + needed. + + + + Zip drives are not the only devices that presented problems for + Linux. There are other devices with pass-through ports, for + example parallel port CD-ROM drives. There are also printers that + report their status textually rather than using simple error pins: + sending a command to the printer can cause it to report the number + of pages that it has ever printed, or how much free memory it has, + or whether it is running out of toner, and so on. The printer + driver didn't originally offer any facility for reading back this + information (although Carsten Gross added nibble mode readback + support for kernel 2.2). + -The first parallel port support for Linux came with the line -printer driver, lp. The printer driver is a -character special device, and (in Linux 2.0) had support for writing, -via write, and configuration and statistics -reporting via ioctl. - -The printer driver could be used on any computer that had an IBM -PC-compatible parallel port. Because some architectures have parallel -ports that aren't really the same as PC-style ports, other variants of -the printer driver were written in order to support Amiga and Atari -parallel ports. - -When the Iomega Zip drive was released, and a driver written for -it, a problem became apparent. The Zip drive is a parallel port -device that provides a parallel port of its own---it is designed to -sit between a computer and an attached printer, with the printer -plugged into the Zip drive, and the Zip drive plugged into the -computer. - -The problem was that, although printers and Zip drives were both -supported, for any given port only one could be used at a time. Only -one of the two drivers could be present in the kernel at once. This -was because of the fact that both drivers wanted to drive the same -hardware---the parallel port. When the printer driver initialised, it -would call the check_region function to make sure -that the IO region associated with the parallel port was free, and -then it would call request_region to allocate it. -The Zip drive used the same mechanism. Whichever driver initialised -first would gain exclusive control of the parallel port. - -The only way around this problem at the time was to make sure -that both drivers were available as loadable kernel modules. To use -the printer, load the printer driver module; then for the Zip drive, -unload the printer driver module and load the Zip driver -module. - -The net effect was that printing a document that was stored on a Zip -drive was a bit of an ordeal, at least if the Zip drive and printer -shared a parallel port. A better solution was needed. - -Zip drives are not the only devices that presented problems for -Linux. There are other devices with pass-through ports, for example -parallel port CD-ROM drives. There are also printers that report -their status textually rather than using simple error pins: sending a -command to the printer can cause it to report the number of pages that -it has ever printed, or how much free memory it has, or whether it is -running out of toner, and so on. The printer driver didn't originally -offer any facility for reading back this information (although Carsten -Gross added nibble mode readback support for kernel 2.2). - - - -The IEEE has issued a standards document called IEEE 1284, which -documents existing practice for parallel port communications in a -variety of modes. Those modes are: compatibility, -reverse nibble, reverse byte, ECP and EPP. Newer devices often use -the more advanced modes of transfer (ECP and EPP). In Linux 2.0, the -printer driver only supported compatibility mode -(i.e. normal printer protocol) and reverse nibble mode. + + The IEEE has issued a standards document called IEEE 1284, which + documents existing practice for parallel port communications in a + variety of modes. Those modes are: compatibility, + reverse nibble, reverse byte, ECP and EPP. Newer devices often + use the more advanced modes of transfer (ECP and EPP). In Linux + 2.0, the printer driver only supported compatibility + mode (i.e. normal printer protocol) and reverse nibble + mode. + - + - -The solutions + + The solutions -The parport code in Linux 2.2 was designed -to meet these problems of architectural differences in parallel ports, -of port-sharing between devices with pass-through ports, and of lack -of support for IEEE 1284 transfer modes. - - - -There are two layers to the -parport subsystem, only one of which deals -directly with the hardware. The other layer deals with sharing and -IEEE 1284 transfer modes. In this way, parallel support for a -particular architecture comes in the form of a module which registers -itself with the generic sharing layer. - - - -The sharing model provided by the parport -subsystem is one of exclusive access. A device driver, such as the -printer driver, must ask the parport layer for -access to the port, and can only use the port once access has been -granted. When it has finished a transaction, it can -tell the parport layer that it may release the -port for other device drivers to use. - - - -Devices with pass-through ports all manage to share a parallel -port with other devices in generally the same way. The device has a -latch for each of the pins on its pass-through port. The normal state -of affairs is pass-through mode, with the device copying the signal -lines between its host port and its pass-through port. When the -device sees a special signal from the host port, it latches the -pass-through port so that devices further downstream don't get -confused by the pass-through device's conversation with the host -parallel port: the device connected to the pass-through port (and any -devices connected in turn to it) are effectively cut off from the -computer. When the pass-through device has completed its transaction -with the computer, it enables the pass-through port again. - - - - - - - -This technique relies on certain special signals -being invisible to devices that aren't watching for them. This tends -to mean only changing the data signals and leaving the control signals -alone. IEEE 1284.3 documents a standard protocol for daisy-chaining -devices together with parallel ports. - - - -Support for standard transfer modes are provided as operations -that can be performed on a port, along with operations for setting the -data lines, or the control lines, or reading the status lines. These -operations appear to the device driver as function pointers; more -later. - - - - - - -Standard transfer modes - - - - -The standard transfer modes in use over the -parallel port are defined by a document called IEEE -1284. It really just codifies existing practice and documents -protocols (and variations on protocols) that have been in common use -for quite some time. - -The original definitions of which pin did what were set out by -Centronics Data Computer Corporation, but only the printer-side -interface signals were specified. - -By the early 1980s, IBM's host-side implementation had become -the most widely used. New printers emerged that claimed Centronics -compatibility, but although compatible with Centronics they differed -from one another in a number of ways. - -As a result of this, when IEEE 1284 was published in 1994, all -that it could really do was document the various protocols that are -used for printers (there are about six variations on a theme). - -In addition to the protocol used to talk to -Centronics-compatible printers, IEEE 1284 defined other protocols that -are used for unidirectional peripheral-to-host transfers (reverse -nibble and reverse byte) and for fast bidirectional transfers (ECP and -EPP). + + The parport code in Linux 2.2 was designed to + meet these problems of architectural differences in parallel + ports, of port-sharing between devices with pass-through ports, + and of lack of support for IEEE 1284 transfer modes. + - + + + + There are two layers to the parport + subsystem, only one of which deals directly with the hardware. + The other layer deals with sharing and IEEE 1284 transfer modes. + In this way, parallel support for a particular architecture comes + in the form of a module which registers itself with the generic + sharing layer. + - -Structure + + + + The sharing model provided by the parport + subsystem is one of exclusive access. A device driver, such as + the printer driver, must ask the parport + layer for access to the port, and can only use the port once + access has been granted. When it has finished a + transaction, it can tell the + parport layer that it may release the port + for other device drivers to use. + + + + + + Devices with pass-through ports all manage to share a parallel + port with other devices in generally the same way. The device has + a latch for each of the pins on its pass-through port. The normal + state of affairs is pass-through mode, with the device copying the + signal lines between its host port and its pass-through port. + When the device sees a special signal from the host port, it + latches the pass-through port so that devices further downstream + don't get confused by the pass-through device's conversation with + the host parallel port: the device connected to the pass-through + port (and any devices connected in turn to it) are effectively cut + off from the computer. When the pass-through device has completed + its transaction with the computer, it enables the pass-through + port again. + + + + + + + + + + + + + This technique relies on certain special signals + being invisible to devices that aren't watching for them. This + tends to mean only changing the data signals and leaving the + control signals alone. IEEE 1284.3 documents a standard protocol + for daisy-chaining devices together with parallel ports. + + + + + + Support for standard transfer modes are provided as operations + that can be performed on a port, along with operations for setting + the data lines, or the control lines, or reading the status lines. + These operations appear to the device driver as function pointers; + more later. + + + + + + + + Standard transfer modes + + + + + + The standard transfer modes in use over the parallel + port are defined by a document called IEEE 1284. It + really just codifies existing practice and documents protocols (and + variations on protocols) that have been in common use for quite + some time. + + + + The original definitions of which pin did what were set out by + Centronics Data Computer Corporation, but only the printer-side + interface signals were specified. + + + + By the early 1980s, IBM's host-side implementation had become the + most widely used. New printers emerged that claimed Centronics + compatibility, but although compatible with Centronics they + differed from one another in a number of ways. + + + + As a result of this, when IEEE 1284 was published in 1994, all that + it could really do was document the various protocols that are used + for printers (there are about six variations on a theme). + + + + In addition to the protocol used to talk to Centronics-compatible + printers, IEEE 1284 defined other protocols that are used for + unidirectional peripheral-to-host transfers (reverse nibble and + reverse byte) and for fast bidirectional transfers (ECP and + EPP). + + + + + + Structure - + + + + + + + + + + + Sharing core + + + At the core of the parport subsystem is the + sharing mechanism (see + drivers/parport/share.c). This module, + parport, is responsible for keeping track of + which ports there are in the system, which device drivers might be + interested in new ports, and whether or not each port is available + for use (or if not, which driver is currently using it). + + + + + + Parports and their overrides + + + The generic parport sharing code doesn't + directly handle the parallel port hardware. That is done instead + by low-level parport drivers. + The function of a low-level parport driver is + to detect parallel ports, register them with the sharing code, and + provide a list of access functions for each port. + + + + The most basic access functions that must be provided are ones for + examining the status lines, for setting the control lines, and for + setting the data lines. There are also access functions for + setting the direction of the data lines; normally they are in the + forward direction (that is, the computer drives + them), but some ports allow switching to reverse + mode (driven by the peripheral). There is an access function for + examining the data lines once in reverse mode. + + + + + + IEEE 1284 transfer modes + + + Stacked on top of the sharing mechanism, but still in the + parport module, are functions for + transferring data. They are provided for the device drivers to + use, and are very much like library routines. Since these + transfer functions are provided by the generic + parport core they must use the lowest + common denominator set of access functions: they can set + the control lines, examine the status lines, and use the data + lines. With some parallel ports the data lines can only be set + and not examined, and with other ports accessing the data register + causes control line activity; with these types of situations, the + IEEE 1284 transfer functions make a best effort attempt to do the + right thing. In some cases, it is not physically possible to use + particular IEEE 1284 transfer modes. + + + + The low-level parport drivers also provide + IEEE 1284 transfer functions, as names in the access function + list. The low-level driver can just name the generic IEEE 1284 + transfer functions for this. Some parallel ports can do IEEE 1284 + transfers in hardware; for those ports, the low-level driver can + provide functions to utilise that feature. + + + + + + + + Pardevices and parport_drivers + + + When a parallel port device driver (such as + lp) initialises it tells the sharing layer + about itself using parport_register_driver. + The information is put into a struct + parport_driver, which is put into a linked list. The + information in a struct parport_driver + really just amounts to some function pointers to callbacks in the + parallel port device driver. + + + + During its initialisation, a low-level port driver tells the + sharing layer about all the ports that it has found (using + parport_register_port), and the sharing layer + creates a struct parport for each of + them. Each struct parport contains + (among other things) a pointer to a struct + parport_operations, which is a list of function + pointers for the various operations that can be performed on a + port. You can think of a struct parport + as a parallel port object, if + object-orientated programming is your thing. The + parport structures are chained in a + linked list, whose head is portlist (in + drivers/parport/share.c). + + + + Once the port has been registered, the low-level port driver + announces it. The parport_announce_port + function walks down the list of parallel port device drivers + (struct parport_drivers) calling the + attach function of each. + + + + Similarly, a low-level port driver can undo the effect of + registering a port with the + parport_unregister_port function, and device + drivers are notified using the detach + callback. + + + + Device drivers can undo the effect of registering themselves with + the parport_unregister_driver + function. + + + + + + + + The IEEE 1284.3 API + + + The ability to daisy-chain devices is very useful, but if every + device does it in a different way it could lead to lots of + complications for device driver writers. Fortunately, the IEEE + are standardising it in IEEE 1284.3, which covers daisy-chain + devices and port multiplexors. + + + + At the time of writing, IEEE 1284.3 has not been published, but + the draft specifies the on-the-wire protocol for daisy-chaining + and multiplexing, and also suggests a programming interface for + using it. That interface (or most of it) has been implemented in + the parport code in Linux. + + + + At initialisation of the parallel port bus, + daisy-chained devices are assigned addresses starting from zero. + There can only be four devices with daisy-chain addresses, plus + one device on the end that doesn't know about daisy-chaining and + thinks it's connected directly to a computer. + + + + Another way of connecting more parallel port devices is to use a + multiplexor. The idea is to have a device that is connected + directly to a parallel port on a computer, but has a number of + parallel ports on the other side for other peripherals to connect + to (two or four ports are allowed). The multiplexor switches + control to different ports under software control---it is, in + effect, a programmable printer switch. + + + + Combining the ability of daisy-chaining five devices together with + the ability to multiplex one parallel port between four gives the + potential to have twenty peripherals connected to the same + parallel port! + + + + In addition, of course, a single computer can have multiple + parallel ports. So, each parallel port peripheral in the system + can be identified with three numbers, or co-ordinates: the + parallel port, the multiplexed port, and the daisy-chain + address. + + + + + + + + + + + + + Each device in the system is numbered at initialisation (by + parport_daisy_init). You can convert between + this device number and its co-ordinates with + parport_device_num and + parport_device_coords. + + + + +#include <parport.h> + + + int parport_device_num + int parport + int mux + int daisy + + + + + + int parport_device_coords + int devnum + int *parport + int *mux + int *daisy + + + + + Any parallel port peripheral will be connected directly or + indirectly to a parallel port on the system, but it won't have a + daisy-chain address if it does not know about daisy-chaining, and + it won't be connected through a multiplexor port if there is no + multiplexor. The special co-ordinate value + -1 is used to indicate these cases. + + + + Two functions are provided for finding devices based on their IEEE + 1284 Device ID: parport_find_device and + parport_find_class. + - - - - - - - -Sharing core - - - -At the core of the parport subsystem is the -sharing mechanism (see drivers/parport/share.c). -This module, parport, is responsible for -keeping track of which ports there are in the system, which device -drivers might be interested in new ports, and whether or not each port -is available for use (or if not, which driver is currently using -it). - - - - -Parports and their overrides - - -The generic parport sharing code doesn't -directly handle the parallel port hardware. That is done instead by -low-level parport drivers. The -function of a low-level parport driver is to -detect parallel ports, register them with the sharing code, and -provide a list of access functions for each port. - -The most basic access functions that must be provided are ones -for examining the status lines, for setting the control lines, and for -setting the data lines. There are also access functions for setting -the direction of the data lines; normally they are in the -forward direction (that is, the computer drives them), -but some ports allow switching to reverse mode (driven -by the peripheral). There is an access function for examining the -data lines once in reverse mode. - - - - -IEEE 1284 transfer modes - - -Stacked on top of the sharing mechanism, but still in the -parport module, are functions for transferring -data. They are provided for the device drivers to use, and are very -much like library routines. Since these transfer functions are -provided by the generic parport core they must -use the lowest common denominator set of access -functions: they can set the control lines, examine the status lines, -and use the data lines. With some parallel ports the data lines can -only be set and not examined, and with other ports accessing the data -register causes control line activity; with these types of situations, -the IEEE 1284 transfer functions make a best effort attempt to do the -right thing. In some cases, it is not physically possible to use -particular IEEE 1284 transfer modes. - -The low-level parport drivers also provide -IEEE 1284 transfer functions, as names in the access function list. -The low-level driver can just name the generic IEEE 1284 transfer -functions for this. Some parallel ports can do IEEE 1284 transfers in -hardware; for those ports, the low-level driver can provide functions -to utilise that feature. - - - - - - - - -Pardevices and parport_drivers - -When a parallel port device driver (such as -lp) initialises it tells the sharing layer about -itself using parport_register_driver. The -information is put into a struct -parport_driver, which is put into a linked list. The -information in a struct parport_driver really -just amounts to some function pointers to callbacks in the parallel -port device driver. - -During its initialisation, a low-level port driver tells the -sharing layer about all the ports that it has found (using -parport_register_port), and the sharing layer -creates a struct parport for each of them. -Each struct parport contains (among other -things) a pointer to a struct -parport_operations, which is a list of function pointers -for the various operations that can be performed on a port. You can -think of a struct parport as a parallel port -object, if object-orientated programming -is your thing. The parport structures are -chained in a linked list, whose head is portlist -(in drivers/parport/share.c). - -Once the port has been registered, the low-level port driver -announces it. The parport_announce_port function -walks down the list of parallel port device drivers -(struct parport_drivers) calling the -attach function of each. - -Similarly, a low-level port driver can undo the effect of -registering a port with the -parport_unregister_port function, and device -drivers are notified using the detach -callback. - -Device drivers can undo the effect of registering themselves -with the parport_unregister_driver -function. - - - - - - -The IEEE 1284.3 API - -The ability to daisy-chain devices is very useful, but if every -device does it in a different way it could lead to lots of -complications for device driver writers. Fortunately, the IEEE are -standardising it in IEEE 1284.3, which covers daisy-chain devices and -port multiplexors. - -At the time of writing, IEEE 1284.3 has not been published, but -the draft specifies the on-the-wire protocol for daisy-chaining and -multiplexing, and also suggests a programming interface for using it. -That interface (or most of it) has been implemented in the -parport code in Linux. - -At initialisation of the parallel port bus, daisy-chained -devices are assigned addresses starting from zero. There can only be -four devices with daisy-chain addresses, plus one device on the end -that doesn't know about daisy-chaining and thinks it's connected -directly to a computer. - -Another way of connecting more parallel port devices is to use a -multiplexor. The idea is to have a device that is connected directly -to a parallel port on a computer, but has a number of parallel ports -on the other side for other peripherals to connect to (two or four -ports are allowed). The multiplexor switches control to different -ports under software control---it is, in effect, a programmable -printer switch. - -Combining the ability of daisy-chaining five devices together -with the ability to multiplex one parallel port between four gives the -potential to have twenty peripherals connected to the same parallel -port! - -In addition, of course, a single computer can have multiple -parallel ports. So, each parallel port peripheral in the system can -be identified with three numbers, or co-ordinates: the parallel port, -the multiplexed port, and the daisy-chain address. - - - - - - - - - - - - - - - -Each device in the system is numbered at initialisation (by -parport_daisy_init). You can convert between -this device number and its co-ordinates with -parport_device_num and -parport_device_coords. - - - int parport_device_num - int parport - int mux - int daisy - - - - int parport_device_coords - int devnum - int *parport - int *mux - int *daisy - - -Any parallel port peripheral will be connected directly or -indirectly to a parallel port on the system, but it won't have a -daisy-chain address if it does not know about daisy-chaining, and it -won't be connected through a multiplexor port if there is no -multiplexor. The special co-ordinate value -1 is -used to indicate these cases. - -Two functions are provided for finding devices based on their -IEEE 1284 Device ID: parport_find_device and -parport_find_class. - - - int parport_find_device - const char *mfg - const char *mdl - int from - - - - int parport_find_class - parport_device_class cls - int from - - -These functions take a device number (in addition to some other -things), and return another device number. They walk through the list -of detected devices until they find one that matches the requirements, -and then return that device number (or -1 if -there are no more such devices). They start their search at the -device after the one in the list with the number given (at -from+1, in other words). + + +#include <parport.h> + + + int parport_find_device + const char *mfg + const char *mdl + int from + + + + + + int parport_find_class + parport_device_class cls + int from + + - + + These functions take a device number (in addition to some other + things), and return another device number. They walk through the + list of detected devices until they find one that matches the + requirements, and then return that device number (or + -1 if there are no more such devices). They + start their search at the device after the one in the list with + the number given (at from+1, in other + words). + - + - -Device driver's view + + + + Device driver's view -This section is written from the point of view of the device -driver programmer, who might be writing a driver for a printer or a -scanner or else anything that plugs into the parallel port. It -explains how to use the parport interface to find -parallel ports, use them, and share them with other device -drivers. - -We'll start out with a description of the various functions that -can be called, and then look at a reasonably simple example of their -use: the printer driver. - -The interactions between the device driver and the -parport layer are as follows. First, the device -driver registers its existence with parport, in -order to get told about any parallel ports that have been (or will be) -detected. When it gets told about a parallel port, it then tells -parport that it wants to drive a device on that -port. Thereafter it can claim exclusive access to the port in order -to talk to its device. - -So, the first thing for the device driver to do is tell -parport that it wants to know what parallel ports -are on the system. To do this, it uses the -parport_register_device function: + + This section is written from the point of view of the device driver + programmer, who might be writing a driver for a printer or a + scanner or else anything that plugs into the parallel port. It + explains how to use the parport interface to + find parallel ports, use them, and share them with other device + drivers. + + + + We'll start out with a description of the various functions that + can be called, and then look at a reasonably simple example of + their use: the printer driver. + + + + The interactions between the device driver and the + parport layer are as follows. First, the + device driver registers its existence with + parport, in order to get told about any + parallel ports that have been (or will be) detected. When it gets + told about a parallel port, it then tells + parport that it wants to drive a device on + that port. Thereafter it can claim exclusive access to the port in + order to talk to its device. + + + + So, the first thing for the device driver to do is tell + parport that it wants to know what parallel + ports are on the system. To do this, it uses the + parport_register_device function: + + + + +#include <parport.h> - - + - - int parport_register_driver - struct parport_driver *driver - - -In other words, the device driver passes pointers to a couple of -functions to parport, and -parport calls attach for -each port that's detected (and detach for each -port that disappears -- yes, this can happen). - -The next thing that happens is that the device driver tells -parport that it thinks there's a device on the -port that it can drive. This typically will happen in the driver's -attach function, and is done with -parport_register_device: - - - struct pardevice *parport_register_device - struct parport *port - const char *name - int (*pf) - void * - void (*kf) - void * - void (*irq_func) - int, void *, struct pt_regs * - int flags - void *handle - - -The port comes from the parameter supplied -to the attach function when it is called, or -alternatively can be found from the list of detected parallel ports -directly with the (now deprecated) -parport_enumerate function. - -The next three parameters, pf, -kf, and irq_func, are -more function pointers. These callback functions get called under -various circumstances, and are always given the -handle as one of their parameters. - -The preemption callback, pf, is called -when the driver has claimed access to the port but another device -driver wants access. If the driver is willing to let the port go, it -should return zero and the port will be released on its behalf. There -is no need to call parport_release. If -pf gets called at a bad time for letting the -port go, it should return non-zero and no action will be taken. It is -good manners for the driver to try to release the port at the earliest -opportunity after its preemption callback is called. - -The kick callback, kf, is -called when the port can be claimed for exclusive access; that is, -parport_claim is guaranteed to succeed inside the -kick callback. If the driver wants to claim the port -it should do so; otherwise, it need not take any action. - -The irq_func callback is called, -predictably, when a parallel port interrupt is generated. But it is -not the only code that hooks on the interrupt. The sequence is this: -the lowlevel driver is the one that has done -request_irq; it then does whatever -hardware-specific things it needs to do to the parallel port hardware -(for PC-style ports, there is nothing special to do); it then tells -the IEEE 1284 code about the interrupt, which may involve reacting to -an IEEE 1284 event, depending on the current IEEE 1284 phase; and -finally the irq_func function is called. - -None of the callback functions are allowed to block. - -The flags are for telling -parport any requirements or hints that are -useful. The only useful value here (other than -0, which is the usual value) is -PARPORT_DEV_EXCL. The point of that flag is to -request exclusive access at all times---once a driver has successfully -called parport_register_device with that flag, no -other device drivers will be able to register devices on that port -(until the successful driver deregisters its device, of -course). - -The PARPORT_DEV_EXCL flag is for preventing -port sharing, and so should only be used when sharing the port with -other device drivers is impossible and would lead to incorrect -behaviour. Use it sparingly! - -Devices can also be registered by device drivers based on their -device numbers (the same device numbers as in the previous -section). - -The parport_open function is similar to -parport_register_device, and -parport_close is the equivalent of -parport_unregister_device. The difference is -that parport_open takes a device number rather -than a pointer to a struct parport. - - - struct pardevice *parport_open - int devnum - int (*pf) - void * - int (*kf) - void * - int (*irqf) - int, void *, struct pt_regs * - int flags - void *handle - - - - void parport_close - struct pardevice *dev - - - - struct pardevice *parport_register_device - struct parport *port - const char *name - int (*pf) - void * - int (*kf) - void * - int (*irqf) - int, void *, struct pt_regs * - int flags - void *handle - - - - void parport_unregister_device - struct pardevice *dev - - -The intended use of these functions is during driver -initialisation while the driver looks for devices that it supports, as -demonstrated by the following code fragment: + + int parport_register_driver + struct parport_driver *driver + + + + + In other words, the device driver passes pointers to a couple of + functions to parport, and + parport calls attach for + each port that's detected (and detach for each + port that disappears---yes, this can happen). + + + + The next thing that happens is that the device driver tells + parport that it thinks there's a device on the + port that it can drive. This typically will happen in the driver's + attach function, and is done with + parport_register_device: + + + + +#include <parport.h> + + + struct pardevice *parport_register_device + struct parport *port + const char *name + int (*pf) + void * + void (*kf) + void * + void (*irq_func) + int, void *, struct pt_regs * + int flags + void *handle + + + + + The port comes from the parameter supplied + to the attach function when it is called, or + alternatively can be found from the list of detected parallel ports + directly with the (now deprecated) + parport_enumerate function. + + + + The next three parameters, pf, + kf, and irq_func, are + more function pointers. These callback functions get called under + various circumstances, and are always given the + handle as one of their parameters. + + + + The preemption callback, pf, is called when + the driver has claimed access to the port but another device driver + wants access. If the driver is willing to let the port go, it + should return zero and the port will be released on its behalf. + There is no need to call parport_release. If + pf gets called at a bad time for letting the + port go, it should return non-zero and no action will be taken. It + is good manners for the driver to try to release the port at the + earliest opportunity after its preemption callback is + called. + + + + The kick callback, kf, is + called when the port can be claimed for exclusive access; that is, + parport_claim is guaranteed to succeed inside + the kick callback. If the driver wants to claim the + port it should do so; otherwise, it need not take any + action. + + + + The irq_func callback is called, + predictably, when a parallel port interrupt is generated. But it + is not the only code that hooks on the interrupt. The sequence is + this: the lowlevel driver is the one that has done + request_irq; it then does whatever + hardware-specific things it needs to do to the parallel port + hardware (for PC-style ports, there is nothing special to do); it + then tells the IEEE 1284 code about the interrupt, which may + involve reacting to an IEEE 1284 event, depending on the current + IEEE 1284 phase; and finally the irq_func + function is called. + + + + None of the callback functions are allowed to block. + + + + The flags are for telling + parport any requirements or hints that are + useful. The only useful value here (other than + 0, which is the usual value) is + PARPORT_DEV_EXCL. The point of that flag is + to request exclusive access at all times---once a driver has + successfully called parport_register_device + with that flag, no other device drivers will be able to register + devices on that port (until the successful driver deregisters its + device, of course). + + + + The PARPORT_DEV_EXCL flag is for preventing + port sharing, and so should only be used when sharing the port with + other device drivers is impossible and would lead to incorrect + behaviour. Use it sparingly! + + + + Devices can also be registered by device drivers based on their + device numbers (the same device numbers as in the previous + section). + + + + The parport_open function is similar to + parport_register_device, and + parport_close is the equivalent of + parport_unregister_device. The difference is + that parport_open takes a device number rather + than a pointer to a struct parport. + + + + +#include <parport.h> + + + struct pardevice *parport_open + int devnum + int (*pf) + void * + int (*kf) + void * + int (*irqf) + int, void *, struct pt_regs * + int flags + void *handle + + + + + + void parport_close + struct pardevice *dev + + + + + + struct pardevice *parport_register_device + struct parport *port + const char *name + int (*pf) + void * + int (*kf) + void * + int (*irqf) + int, void *, struct pt_regs * + int flags + void *handle + + + + + + void parport_unregister_device + struct pardevice *dev + + + + + The intended use of these functions is during driver initialisation + while the driver looks for devices that it supports, as + demonstrated by the following code fragment: + - - + + ]]> -Once your device driver has registered its device and been -handed a pointer to a struct pardevice, the -next thing you are likely to want to do is communicate with the device -you think is there. To do that you'll need to claim access to the -port. - - - int parport_claim - struct pardevice *dev - - - - int parport_claim_or_block - struct pardevice *dev - - - - void parport_release - struct pardevice *dev - - -To claim access to the port, use -parport_claim or -parport_claim_or_block. The first of these will -not block, and so can be used from interrupt context. If -parport_claim succeeds it will return zero and -the port is available to use. It may fail (returning non-zero) if the -port is in use by another driver and that driver is not willing to -relinquish control of the port. - -The other function, parport_claim_or_block, -will block if necessary to wait for the port to be free. If it slept, -it returns 1; if it succeeded without needing to -sleep it returns 0. If it fails it will return a -negative error code. - -When you have finished communicating with the device, you can -give up access to the port so that other drivers can communicate with -their devices. The parport_release function -cannot fail, but it should not be called without the port claimed. -Similarly, you should not try to claim the port if you already have it -claimed. - -You may find that although there are convenient points for your -driver to relinquish the parallel port and allow other drivers to talk -to their devices, it would be preferable to keep hold of the port. -The printer driver only needs the port when there is data to print, -for example, but a network driver (such as PLIP) could be sent a -remote packet at any time. With PLIP, it is no huge catastrophe if a -network packet is dropped, since it will likely be sent again, so it -is possible for that kind of driver to share the port with other -(pass-through) devices. - -The parport_yield and -parport_yield_blocking functions are for marking -points in the driver at which other drivers may claim the port and use -their devices. Yielding the port is similar to releasing it and -reclaiming it, but it more efficient because nothing is done if there -are no other devices needing the port. In fact, nothing is done even -if there are other devices waiting but the current device is still -within its timeslice. The default timeslice is half a -second, but it can be adjusted via a /proc -entry. - - - int parport_yield - struct pardevice *dev - - - - int parport_yield_blocking - struct pardevice *dev - - -The first of these, parport_yield, will not -block but as a result may fail. The return value for -parport_yield is the same as for -parport_claim. The blocking version, -parport_yield_blocking, has the same return code -as parport_claim_or_block. - -Once the port has been claimed, the device driver can use the -functions in the struct parport_operations -pointer in the struct parport it has a -pointer to. For example: + + Once your device driver has registered its device and been handed a + pointer to a struct pardevice, the next + thing you are likely to want to do is communicate with the device + you think is there. To do that you'll need to claim access to the + port. + + + + +#include <parport.h> + + + int parport_claim + struct pardevice *dev + + + + + + int parport_claim_or_block + struct pardevice *dev + + + + + + void parport_release + struct pardevice *dev + + + + + To claim access to the port, use parport_claim + or parport_claim_or_block. The first of these + will not block, and so can be used from interrupt context. If + parport_claim succeeds it will return zero and + the port is available to use. It may fail (returning non-zero) if + the port is in use by another driver and that driver is not willing + to relinquish control of the port. + + + + The other function, parport_claim_or_block, + will block if necessary to wait for the port to be free. If it + slept, it returns 1; if it succeeded without + needing to sleep it returns 0. If it fails it + will return a negative error code. + + + + When you have finished communicating with the device, you can give + up access to the port so that other drivers can communicate with + their devices. The parport_release function + cannot fail, but it should not be called without the port claimed. + Similarly, you should not try to claim the port if you already have + it claimed. + + + + You may find that although there are convenient points for your + driver to relinquish the parallel port and allow other drivers to + talk to their devices, it would be preferable to keep hold of the + port. The printer driver only needs the port when there is data to + print, for example, but a network driver (such as PLIP) could be + sent a remote packet at any time. With PLIP, it is no huge + catastrophe if a network packet is dropped, since it will likely be + sent again, so it is possible for that kind of driver to share the + port with other (pass-through) devices. + + + + The parport_yield and + parport_yield_blocking functions are for + marking points in the driver at which other drivers may claim the + port and use their devices. Yielding the port is similar to + releasing it and reclaiming it, but is more efficient because + nothing is done if there are no other devices needing the port. In + fact, nothing is done even if there are other devices waiting but + the current device is still within its timeslice. + The default timeslice is half a second, but it can be adjusted via + a /proc entry. + + + + +#include <parport.h> + + + int parport_yield + struct pardevice *dev + + + + + + int parport_yield_blocking + struct pardevice *dev + + + + + The first of these, parport_yield, will not + block but as a result may fail. The return value for + parport_yield is the same as for + parport_claim. The blocking version, + parport_yield_blocking, has the same return + code as parport_claim_or_block. + + + + Once the port has been claimed, the device driver can use the + functions in the struct parport_operations + pointer in the struct parport it has a + pointer to. For example: + - - + ops->write_data (port, d); -]]> + ]]> -Some of these operations have shortcuts. For -instance, parport_write_data is equivalent to the -above, but may be a little bit faster (it's a macro that in some cases -can avoid needing to indirect through port and -ops). - - - - -Port drivers - - - -To recap, then: - - - - - -The device driver registers itself with parport. - - - - - -A low-level driver finds a parallel port and registers it with -parport (these first two things can happen in -either order). This registration creates a struct -parport which is linked onto a list of known ports. - - - - - -parport calls the attach -function of each registered device driver, passing it the pointer to -the new struct parport. - - - - - -The device driver gets a handle from parport, for -use with -parport_claim/release. This -handle takes the form of a pointer to a struct -pardevice, representing a particular device on the -parallel port, and is acquired using -parport_register_device. - - - - - -The device driver claims the port using -parport_claim (or -function_claim_or_block). - - - - - -Then it goes ahead and uses the port. When finished it releases the -port. - - - - - -The purpose of the low-level drivers, then, is to detect -parallel ports and provide methods of accessing them -(i.e. implementing the operations in struct -parport_operations). - - - - - - -A more complete description of which operation is supposed to do -what is available in -Documentation/parport-lowlevel.txt. - - - - -The printer driver - - - - -The printer driver, lp is a character -special device driver and a parport client. As a -character special device driver it registers a struct -file_operations using -register_chrdev, with pointers filled in for -write, ioctl, -open and -release. As a client of -parport, it registers a struct -parport_driver using -parport_register_driver, so that -parport knows to call -lp_attach when a new parallel port is discovered -(and lp_detach when it goes away). - -The parallel port console functionality is also implemented in -lp.c, but that won't be covered here (it's quite -simple though). - -The initialisation of the driver is quite easy to understand -(see lp_init). The lp_table -is an array of structures that contain information about a specific -device (the struct pardevice associated with -it, for example). That array is initialised to sensible values first -of all. - -Next, the printer driver calls -register_chrdev passing it a pointer to -lp_fops, which contains function pointers for the -printer driver's implementation of open, -write, and so on. This part is the same as for -any character special device driver. - -After successfully registering itself as a character special -device driver, the printer driver registers itself as a -parport client using -parport_register_driver. It passes a pointer to -this structure: + + Some of these operations have shortcuts. For + instance, parport_write_data is equivalent to + the above, but may be a little bit faster (it's a macro that in + some cases can avoid needing to indirect through + port and ops). + + + + + + Port drivers + + + + + To recap, then: + + + + + + The device driver registers itself with parport. + + + + + + A low-level driver finds a parallel port and registers it with + parport (these first two things can happen + in either order). This registration creates a struct + parport which is linked onto a list of known ports. + + + + + + parport calls the + attach function of each registered device + driver, passing it the pointer to the new struct + parport. + + + + + + The device driver gets a handle from + parport, for use with + parport_claim/release. + This handle takes the form of a pointer to a struct + pardevice, representing a particular device on the + parallel port, and is acquired using + parport_register_device. + + + + + + The device driver claims the port using + parport_claim (or + function_claim_or_block). + + + + + + Then it goes ahead and uses the port. When finished it releases + the port. + + + + + + + The purpose of the low-level drivers, then, is to detect parallel + ports and provide methods of accessing them (i.e. implementing the + operations in struct + parport_operations). + + + + + A more complete description of which operation is supposed to do + what is available in + Documentation/parport-lowlevel.txt. + + + + + + The printer driver + + + + + + The printer driver, lp is a character special + device driver and a parport client. As a + character special device driver it registers a struct + file_operations using + register_chrdev, with pointers filled in for + write, ioctl, + open and + release. As a client of + parport, it registers a struct + parport_driver using + parport_register_driver, so that + parport knows to call + lp_attach when a new parallel port is + discovered (and lp_detach when it goes + away). + + + + The parallel port console functionality is also implemented in + drivers/char/lp.c, but that won't be covered + here (it's quite simple though). + + + + The initialisation of the driver is quite easy to understand (see + lp_init). The lp_table is + an array of structures that contain information about a specific + device (the struct pardevice associated + with it, for example). That array is initialised to sensible + values first of all. + + + + Next, the printer driver calls register_chrdev + passing it a pointer to lp_fops, which contains + function pointers for the printer driver's implementation of + open, write, and so on. + This part is the same as for any character special device + driver. + + + + After successfully registering itself as a character special device + driver, the printer driver registers itself as a + parport client using + parport_register_driver. It passes a pointer + to this structure: + - - + + ]]> -The lp_detach function is not very -interesting (it does nothing); the interesting bit is -lp_attach. What goes on here depends on whether -the user supplied any parameters. The possibilities are: no -parameters supplied, in which case the printer driver uses every port -that is detected; the user supplied the parameter auto, -in which case only ports on which the device ID string indicates a -printer is present are used; or the user supplied a list of parallel -port numbers to try, in which case only those are used. - -For each port that the printer driver wants to use (see -lp_register), it calls -parport_register_device and stores the resulting -struct pardevice pointer in the -lp_table. If the user told it to do so, it then -resets the printer. - -The other interesting piece of the printer driver, from the -point of view of parport, is -lp_write. In this function, the user space -process has data that it wants printed, and the printer driver hands -it off to the parport code to deal with. - -The parport functions it uses that we have -not seen yet are parport_negotiate, -parport_set_timeout, and -parport_write. These functions are part of the -IEEE 1284 implementation. - -The way the IEEE 1284 protocol works is that the host tells the -peripheral what transfer mode it would like to use, and the peripheral -either accepts that mode or rejects it; if the mode is rejected, the -host can try again with a different mode. This is the negotation -phase. Once the peripheral has accepted a particular transfer mode, -data transfer can begin that mode. - -The particular transfer mode that the printer driver wants to -use is named in IEEE 1284 as compatibility mode, and -the function to request a particular mode is called -parport_negotiate. - - - int parport_negotiate - struct parport *port - int mode - - -The modes parameter is a symbolic -constant representing an IEEE 1284 mode; in this instance, it is -IEEE1284_MODE_COMPAT. (Compatibility mode is -slightly different to the other modes---rather than being specifically -requested, it is the default until another mode is selected.) - -Back to lp_write then. First, access to -the parallel port is secured with -parport_claim_or_block. At this point the driver -might sleep, waiting for another driver (perhaps a Zip drive driver, -for instance) to let the port go. Next, it goes to compatibility mode -using parport_negotiate. - -The main work is done in the write-loop. In particular, the -line that hands the data over to parport -reads: + + The lp_detach function is not very interesting + (it does nothing); the interesting bit is + lp_attach. What goes on here depends on + whether the user supplied any parameters. The possibilities are: + no parameters supplied, in which case the printer driver uses every + port that is detected; the user supplied the parameter + auto, in which case only ports on which the device + ID string indicates a printer is present are used; or the user + supplied a list of parallel port numbers to try, in which case only + those are used. + + + + For each port that the printer driver wants to use (see + lp_register), it calls + parport_register_device and stores the + resulting struct pardevice pointer in the + lp_table. If the user told it to do so, it then + resets the printer. + + + + The other interesting piece of the printer driver, from the point + of view of parport, is + lp_write. In this function, the user space + process has data that it wants printed, and the printer driver + hands it off to the parport code to deal with. + + + + The parport functions it uses that we have not + seen yet are parport_negotiate, + parport_set_timeout, and + parport_write. These functions are part of + the IEEE 1284 implementation. + + + + The way the IEEE 1284 protocol works is that the host tells the + peripheral what transfer mode it would like to use, and the + peripheral either accepts that mode or rejects it; if the mode is + rejected, the host can try again with a different mode. This is + the negotation phase. Once the peripheral has accepted a + particular transfer mode, data transfer can begin that mode. + + + + The particular transfer mode that the printer driver wants to use + is named in IEEE 1284 as compatibility mode, and the + function to request a particular mode is called + parport_negotiate. + + + + +#include <parport.h> + + + int parport_negotiate + struct parport *port + int mode + + + + + The modes parameter is a symbolic constant + representing an IEEE 1284 mode; in this instance, it is + IEEE1284_MODE_COMPAT. (Compatibility mode is + slightly different to the other modes---rather than being + specifically requested, it is the default until another mode is + selected.) + + + + Back to lp_write then. First, access to the + parallel port is secured with + parport_claim_or_block. At this point the + driver might sleep, waiting for another driver (perhaps a Zip drive + driver, for instance) to let the port go. Next, it goes to + compatibility mode using parport_negotiate. + + + + The main work is done in the write-loop. In particular, the line + that hands the data over to parport reads: + -The parport_write function writes data to -the peripheral using the currently selected transfer mode -(compatibility mode, in this case). It returns the number of bytes -successfully written: - - - ssize_t parport_write - struct parport *port - const void *buf - size_t len - - - - ssize_t parport_read - struct parport *port - void *buf - size_t len - - -(parport_read does what it sounds like, but -only works for modes in which reverse transfer is possible. Of -course, parport_write only works in modes in -which forward transfer is possible, too.) - -The buf pointer should be to kernel space -memory, and obviously the len parameter -specifies the amount of data to transfer. - -In fact what parport_write does is call the -appropriate block transfer function from the struct -parport_operations: + + The parport_write function writes data to the + peripheral using the currently selected transfer mode + (compatibility mode, in this case). It returns the number of bytes + successfully written: + + + + +#include <parport.h> + + + ssize_t parport_write + struct parport *port + const void *buf + size_t len + + + + + + ssize_t parport_read + struct parport *port + void *buf + size_t len + + + + + (parport_read does what it sounds like, but + only works for modes in which reverse transfer is possible. Of + course, parport_write only works in modes in + which forward transfer is possible, too.) + + + + The buf pointer should be to kernel space + memory, and obviously the len parameter + specifies the amount of data to transfer. + + + + In fact what parport_write does is call the + appropriate block transfer function from the struct + parport_operations: + - - + + ]]> -The transfer code in parport will tolerate -a data transfer stall only for so long, and this timeout can be -specified with parport_set_timeout, which returns -the previous timeout: - - - long parport_set_timeout - struct pardevice *dev - long inactivity - - -This timeout is specific to the device, and is restored on -parport_claim. - - - - -User-level device drivers - - - -Introduction to ppdev - -The printer is accessible through /dev/lp0; -in the same way, the parallel port itself is accessible through -/dev/parport0. The difference is in the level of -control that you have over the wires in the parallel port -cable. - -With the printer driver, a user-space program (such as the -printer spooler) can send bytes in printer protocol. -Briefly, this means that for each byte, the eight data lines are set -up, then a strobe line tells the printer to look at the -data lines, and the printer sets an acknowledgement -line to say that it got the byte. The printer driver also allows the -user-space program to read bytes in nibble mode, which -is a way of transferring data from the peripheral to the computer half -a byte at a time (and so it's quite slow). - -In contrast, the ppdev driver (accessed via -/dev/parport0) allows you to: - - - - - -examine status lines, - - - - - -set control lines, - - - - - -set/examine data lines (and control the direction of the data lines), - - - - - -wait for an interrupt (triggered by one of the status lines), - - - - - -find out how many new interrupts have occurred, - - - - - -set up a response to an interrupt, - - - - - -use IEEE 1284 negotiation (for telling peripheral which transfer mode, -to use) - - - - - -transfer data using a specified IEEE 1284 mode. - - - - - - - - -User-level or kernel-level driver? - -The decision of whether to choose to write a kernel-level device -driver or a user-level device driver depends on several factors. One -of the main ones from a practical point of view is speed: kernel-level -device drivers get to run faster because they are not preemptable, -unlike user-level applications. - -Another factor is ease of development. It is in general easier -to write a user-level driver because (a) one wrong move does not -result in a crashed machine, (b) you have access to user libraries -(such as the C library), and (c) debugging is easier. - - - - -Programming interface - -The ppdev interface is largely the same as -that of other character special devices, in that it supports -open, close, -read, write, and -ioctl. - - -Starting and stopping: <function>open</function> and -<function>close</function> - -The device node /dev/parport0 represents -any device that is connected to parport0, the -first parallel port in the system. Each time the device node is -opened, it represents (to the process doing the opening) a different -device. It can be opened more than once, but only one instance can -actually be in control of the parallel port at any time. A process -that has opened /dev/parport0 shares the parallel -port in the same way as any other device driver. A user-land driver -may be sharing the parallel port with in-kernel device drivers as well -as other user-land drivers. - - - -Control: <function>ioctl</function> - -Most of the control is done, naturally enough, via the -ioctl call. Using ioctl, -the user-land driver can control both the ppdev -driver in the kernel and the physical parallel port itself. The -ioctl call takes as parameters a file descriptor -(the one returned from opening the device node), a command, and -optionally (a pointer to) some data. - - -PPCLAIM - - -Claims access to the port. As a user-land device driver writer, -you will need to do this before you are able to actually change the -state of the parallel port in any way. Note that some operations only -affect the ppdev driver and not the port, such as -PPSETMODE; they can be performed while access to -the port is not claimed. - - - -PPEXCL - - -Instructs the kernel driver to forbid any sharing of the port -with other drivers, i.e. it requests exclusivity. The -PPEXCL command is only valid when the port is not -already claimed for use, and it may mean that the next -PPCLAIM ioctl will fail: -some other driver may already have registered itself on that -port. - -Most device drivers don't need exclusive access to the port. -It's only provided in case it is really needed, for example for -devices where access to the port is required for extensive periods of -time (many seconds). - -Note that the PPEXCL -ioctl doesn't actually claim the port there and -then---action is deferred until the PPCLAIM -ioctl is performed. - - - -PPRELEASE - - -Releases the port. Releasing the port undoes the effect of -claiming the port. It allows other device drivers to talk to their -devices (assuming that there are any). - - - -PPYIELD - - -Yields the port to another driver. This -ioctl is a kind of short-hand for releasing the -port and immediately reclaiming it. It gives other drivers a chance -to talk to their devices, but afterwards claims the port back. An -example of using this would be in a user-land printer driver: once a -few characters have been written we could give the port to another -device driver for a while, but if we still have characters to send to -the printer we would want the port back as soon as possible. - -It is important not to claim the parallel port for too long, as -other device drivers will have no time to service their devices. If -your device does not allow for parallel port sharing at all, it is -better to claim the parallel port exclusively (see -PPEXCL). - - - -PPNEGOT - - -Performs IEEE 1284 negotiation into a particular mode. Briefly, -negotiation is the method by which the host and the peripheral decide -on a protocol to use when transferring data. - -An IEEE 1284 compliant device will start out in compatibility -mode, and then the host can negotiate to another mode (such as -ECP). - -The ioctl parameter should be a pointer to -an int; values for this are in -parport.h and include: - - -IEEE1284_MODE_COMPAT -IEEE1284_MODE_NIBBLE -IEEE1284_MODE_BYTE -IEEE1284_MODE_EPP -IEEE1284_MODE_ECP - - -The PPNEGOT ioctl -actually does two things: it performs the on-the-wire negotiation, and -it sets the behaviour of subsequent -read/write calls so that -they use that mode (but see PPSETMODE). - - - -PPSETMODE - - -Sets which IEEE 1284 protocol to use for the -read and write calls. - -The ioctl parameter should be a pointer to -an int. - - - -PPGETTIME - - -Retrieves the time-out value. The read and -write calls will time out if the peripheral -doesn't respond quickly enough. The PPGETTIME -ioctl retrieves the length of time that the -peripheral is allowed to have before giving up. - -The ioctl parameter should be a pointer to -a struct timeval. - - - -PPSETTIME - - -Sets the time-out. The ioctl parameter -should be a pointer to a struct -timeval. - - - -PPWCONTROL - - -Sets the control lines. The ioctl -parameter is a pointer to an unsigned char, the bitwise -OR of the control line values in -parport.h. - - - -PPRCONTROL - - -Returns the last value written to the control register, in the -form of an unsigned char: each bit corresponds to a -control line (although some are unused). The -ioctl parameter should be a pointer to an -unsigned char. - -This doesn't actually touch the hardware; the last value written -is remembered in software. This is because some parallel port -hardware does not offer read access to the control register. - -The control lines bits are defined in -parport.h: - - -PARPORT_CONTROL_STROBE -PARPORT_CONTROL_AUTOFD -PARPORT_CONTROL_SELECT -PARPORT_CONTROL_INIT - - - - -PPFCONTROL - - -Frobs the control lines. Since a common operation is to change -one of the control signals while leaving the others alone, it would be -quite inefficient for the user-land driver to have to use -PPRCONTROL, make the change, and then use -PPWCONTROL. Of course, each driver could -remember what state the control lines are supposed to be in (they are -never changed by anything else), but in order to provide -PPRCONTROL, ppdev must -remember the state of the control lines anyway. - -The PPFCONTROL ioctl -is for frobbing control lines, and is like -PPWCONTROL but acts on a restricted set of -control lines. The ioctl parameter is a pointer -to a struct ppdev_frob_struct: + + The transfer code in parport will tolerate a + data transfer stall only for so long, and this timeout can be + specified with parport_set_timeout, which + returns the previous timeout: + + + + +#include <parport.h> + + + long parport_set_timeout + struct pardevice *dev + long inactivity + + + + + This timeout is specific to the device, and is restored on + parport_claim. + + + + The next function to look at is the one that allows processes to + read from /dev/lp0: + lp_read. It's short, like + lp_write. + + + + The semantics of reading from a line printer device are as follows: + + + + + + Switch to reverse nibble mode. + + + + + + Try to read data from the peripheral using reverse nibble mode, + until either the user-provided buffer is full or the peripheral + indicates that there is no more data. + + + + + + If there was data, stop, and return it. + + + + + + Otherwise, we tried to read data and there was none. If the user + opened the device node with the O_NONBLOCK + flag, return. Otherwise wait until an interrupt occurs on the + port (or a timeout elapses). + + + + + + + + User-level device drivers + + + + Introduction to ppdev - - - - -The mask and -val fields are bitwise ORs of control line -names (such as in PPWCONTROL). The operation -performed by PPFCONTROL is: - - - - - -In other words, the signals named in -mask are set to the values in -val. - - - -PPRSTATUS - - -Returns an unsigned char containing bits set for -each status line that is set (for instance, -PARPORT_STATUS_BUSY). The -ioctl parameter should be a pointer to an -unsigned char. - - - -PPDATADIR - - -Controls the data line drivers. Normally the computer's -parallel port will drive the data lines, but for byte-wide transfers -from the peripheral to the host it is useful to turn off those drivers -and let the peripheral drive the signals. (If the drivers on the -computer's parallel port are left on when this happens, the port might -be damaged.) - -This is only needed in conjunction with -PPWDATA or PPRDATA. - -The ioctl parameter is a pointer to an -int. If the int is zero, the drivers are -turned on (forward direction); if non-zero, the drivers are turned off -(reverse direction). - - - -PPWDATA - - -Sets the data lines (if in forward mode). The -ioctl parameter is a pointer to an unsigned -char. - - - -PPRDATA - - -Reads the data lines (if in reverse mode). The -ioctl parameter is a pointer to an unsigned -char. - - - -PPCLRIRQ - + + The printer is accessible through /dev/lp0; + in the same way, the parallel port itself is accessible through + /dev/parport0. The difference is in the + level of control that you have over the wires in the parallel port + cable. + -Clears the interrupt count. The ppdev -driver keeps a count of interrupts as they are triggered. -PPCLRIRQ stores this count in an -int, a pointer to which is passed in as the -ioctl parameter. + + With the printer driver, a user-space program (such as the printer + spooler) can send bytes in printer protocol. + Briefly, this means that for each byte, the eight data lines are + set up, then a strobe line tells the printer to + look at the data lines, and the printer sets an + acknowledgement line to say that it got the byte. + The printer driver also allows the user-space program to read + bytes in nibble mode, which is a way of + transferring data from the peripheral to the computer half a byte + at a time (and so it's quite slow). + -In addition, the interrupt count is reset to zero. + + In contrast, the ppdev driver (accessed via + /dev/parport0) allows you to: + - + -PPWCTLONIRQ - + + + examine status lines, + + + + + + set control lines, + + + + + + set/examine data lines (and control the direction of the data + lines), + + + + + + wait for an interrupt (triggered by one of the status lines), + + + + + + find out how many new interrupts have occurred, + + + + + + set up a response to an interrupt, + + + + + + use IEEE 1284 negotiation (for telling peripheral which transfer + mode, to use) + + + + + + transfer data using a specified IEEE 1284 mode. + + -Set a trigger response. Afterwards when an interrupt is -triggered, the interrupt handler will set the control lines as -requested. The ioctl parameter is a pointer to -an unsigned char, which is interpreted in the same way as -for PPWCONTROL. + -The reason for this ioctl is simply speed. -Without this ioctl, responding to an interrupt -would start in the interrupt handler, switch context to the user-land -driver via poll or select, -and then switch context back to the kernel in order to handle -PPWCONTROL. Doing the whole lot in the interrupt -handler is a lot faster. + - + + User-level or kernel-level driver? - + + The decision of whether to choose to write a kernel-level device + driver or a user-level device driver depends on several factors. + One of the main ones from a practical point of view is speed: + kernel-level device drivers get to run faster because they are not + preemptable, unlike user-level applications. + - + + Another factor is ease of development. It is in general easier to + write a user-level driver because (a) one wrong move does not + result in a crashed machine, (b) you have access to user libraries + (such as the C library), and (c) debugging is easier. + - + - -Transferring data: <function>read</function> and -<function>write</function> + + Programming interface -Transferring data using read and -write is straightforward. The data is -transferring using the current IEEE 1284 mode (see the -PPSETMODE ioctl). For modes -which can only transfer data in one direction, only the appropriate -function will work, of course. - + + The ppdev interface is largely the same as that + of other character special devices, in that it supports + open, close, + read, write, and + ioctl. The constants for the + ioctl commands are in + include/linux/ppdev.h. + - -Waiting for events: <function>poll</function> and -<function>select</function> + + + Starting and stopping: <function>open</function> and + <function>close</function> + + + + The device node /dev/parport0 represents any + device that is connected to parport0, the + first parallel port in the system. Each time the device node is + opened, it represents (to the process doing the opening) a + different device. It can be opened more than once, but only one + instance can actually be in control of the parallel port at any + time. A process that has opened + /dev/parport0 shares the parallel port in + the same way as any other device driver. A user-land driver may + be sharing the parallel port with in-kernel device drivers as + well as other user-land drivers. + + + + + Control: <function>ioctl</function> + + + Most of the control is done, naturally enough, via the + ioctl call. Using + ioctl, the user-land driver can control both + the ppdev driver in the kernel and the + physical parallel port itself. The ioctl + call takes as parameters a file descriptor (the one returned from + opening the device node), a command, and optionally (a pointer + to) some data. + + + + PPCLAIM + + + + Claims access to the port. As a user-land device driver + writer, you will need to do this before you are able to + actually change the state of the parallel port in any way. + Note that some operations only affect the + ppdev driver and not the port, such as + PPSETMODE; they can be performed while + access to the port is not claimed. + + + + + PPEXCL + + + + Instructs the kernel driver to forbid any sharing of the port + with other drivers, i.e. it requests exclusivity. The + PPEXCL command is only valid when the + port is not already claimed for use, and it may mean that the + next PPCLAIM ioctl + will fail: some other driver may already have registered + itself on that port. + + + + Most device drivers don't need exclusive access to the port. + It's only provided in case it is really needed, for example + for devices where access to the port is required for extensive + periods of time (many seconds). + + + + Note that the PPEXCL + ioctl doesn't actually claim the port + there and then---action is deferred until the + PPCLAIM ioctl is + performed. + + + + + PPRELEASE + + + + Releases the port. Releasing the port undoes the effect of + claiming the port. It allows other device drivers to talk to + their devices (assuming that there are any). + + + + + PPYIELD + + + + Yields the port to another driver. This + ioctl is a kind of short-hand for + releasing the port and immediately reclaiming it. It gives + other drivers a chance to talk to their devices, but + afterwards claims the port back. An example of using this + would be in a user-land printer driver: once a few characters + have been written we could give the port to another device + driver for a while, but if we still have characters to send to + the printer we would want the port back as soon as possible. + + + + It is important not to claim the parallel port for too long, + as other device drivers will have no time to service their + devices. If your device does not allow for parallel port + sharing at all, it is better to claim the parallel port + exclusively (see PPEXCL). + + + + + PPNEGOT + + + + Performs IEEE 1284 negotiation into a particular mode. + Briefly, negotiation is the method by which the host and the + peripheral decide on a protocol to use when transferring data. + + + + An IEEE 1284 compliant device will start out in compatibility + mode, and then the host can negotiate to another mode (such as + ECP). + + + + The ioctl parameter should be a pointer + to an int; values for this are in + incluce/linux/parport.h and include: + + + + + IEEE1284_MODE_COMPAT + + IEEE1284_MODE_NIBBLE + + IEEE1284_MODE_BYTE + + IEEE1284_MODE_EPP + + IEEE1284_MODE_ECP + + + + The PPNEGOT ioctl + actually does two things: it performs the on-the-wire + negotiation, and it sets the behaviour of subsequent + read/write calls so + that they use that mode (but see + PPSETMODE). + + + + + PPSETMODE + + + + Sets which IEEE 1284 protocol to use for the + read and write + calls. + + + + The ioctl parameter should be a pointer + to an int. + + + + + PPGETTIME + + + + Retrieves the time-out value. The read + and write calls will time out if the + peripheral doesn't respond quickly enough. The + PPGETTIME ioctl + retrieves the length of time that the peripheral is allowed to + have before giving up. + + + + The ioctl parameter should be a pointer + to a struct timeval. + + + + + PPSETTIME + + + + Sets the time-out. The ioctl parameter + should be a pointer to a struct + timeval. + + + + + PPWCONTROL + + + + Sets the control lines. The ioctl + parameter is a pointer to an unsigned char, the + bitwise OR of the control line values in + include/linux/parport.h. + + + + + PPRCONTROL + + + + Returns the last value written to the control register, in the + form of an unsigned char: each bit corresponds to + a control line (although some are unused). The + ioctl parameter should be a pointer to an + unsigned char. + + + + This doesn't actually touch the hardware; the last value + written is remembered in software. This is because some + parallel port hardware does not offer read access to the + control register. + + + + The control lines bits are defined in + include/linux/parport.h: + + + + + PARPORT_CONTROL_STROBE + + PARPORT_CONTROL_AUTOFD + + PARPORT_CONTROL_SELECT + + PARPORT_CONTROL_INIT + + + + + PPFCONTROL + + + + Frobs the control lines. Since a common operation is to + change one of the control signals while leaving the others + alone, it would be quite inefficient for the user-land driver + to have to use PPRCONTROL, make the + change, and then use PPWCONTROL. Of + course, each driver could remember what state the control + lines are supposed to be in (they are never changed by + anything else), but in order to provide + PPRCONTROL, ppdev + must remember the state of the control lines anyway. + + + + The PPFCONTROL ioctl + is for frobbing control lines, and is like + PPWCONTROL but acts on a restricted set + of control lines. The ioctl parameter is + a pointer to a struct + ppdev_frob_struct: + -The ppdev driver provides user-land device -drivers with the ability to wait for interrupts, and this is done -using poll (and select, -which is implemented in terms of poll). + + + -When a user-land device driver wants to wait for an interrupt, -it sleeps with poll. When the interrupt arrives, -ppdev wakes it up (with a read -event, although strictly speaking there is nothing to actually -read). + + The mask and + val fields are bitwise ORs of + control line names (such as in + PPWCONTROL). The operation performed by + PPFCONTROL is: + + + + + + + + In other words, the signals named in + mask are set to the values in + val. + + + + + PPRSTATUS + + + + Returns an unsigned char containing bits set for + each status line that is set (for instance, + PARPORT_STATUS_BUSY). The + ioctl parameter should be a pointer to an + unsigned char. + + + + + PPDATADIR + + + + Controls the data line drivers. Normally the computer's + parallel port will drive the data lines, but for byte-wide + transfers from the peripheral to the host it is useful to turn + off those drivers and let the peripheral drive the + signals. (If the drivers on the computer's parallel port are + left on when this happens, the port might be damaged.) + + + + This is only needed in conjunction with + PPWDATA or + PPRDATA. + + + + The ioctl parameter is a pointer to an + int. If the int is zero, the + drivers are turned on (forward direction); if non-zero, the + drivers are turned off (reverse direction). + + + + + PPWDATA + + + + Sets the data lines (if in forward mode). The + ioctl parameter is a pointer to an + unsigned char. + + + + + PPRDATA + + + + Reads the data lines (if in reverse mode). The + ioctl parameter is a pointer to an + unsigned char. + + + + + PPCLRIRQ + + + + Clears the interrupt count. The ppdev + driver keeps a count of interrupts as they are triggered. + PPCLRIRQ stores this count in an + int, a pointer to which is passed in as the + ioctl parameter. + + + + In addition, the interrupt count is reset to zero. + + + + + PPWCTLONIRQ + + + + Set a trigger response. Afterwards when an interrupt is + triggered, the interrupt handler will set the control lines as + requested. The ioctl parameter is a + pointer to an unsigned char, which is interpreted + in the same way as for PPWCONTROL. + + + + The reason for this ioctl is simply + speed. Without this ioctl, responding to + an interrupt would start in the interrupt handler, switch + context to the user-land driver via poll + or select, and then switch context back + to the kernel in order to handle + PPWCONTROL. Doing the whole lot in the + interrupt handler is a lot faster. + + + + + + + + + + + + Transferring data: <function>read</function> and + <function>write</function> + + + Transferring data using read and + write is straightforward. The data is + transferring using the current IEEE 1284 mode (see the + PPSETMODE ioctl). For + modes which can only transfer data in one direction, only the + appropriate function will work, of course. + + + + + Waiting for events: <function>poll</function> and + <function>select</function> + + + The ppdev driver provides user-land device + drivers with the ability to wait for interrupts, and this is done + using poll (and select, + which is implemented in terms of poll). + + + + When a user-land device driver wants to wait for an interrupt, it + sleeps with poll. When the interrupt + arrives, ppdev wakes it up (with a + read event, although strictly speaking there is + nothing to actually read). + - + - + - -Examples + + Examples -Presented here are two demonstrations of how to write a simple -printer driver for ppdev. Firstly we will use -the write function, and after that we will drive -the control and data lines directly. + + Presented here are two demonstrations of how to write a simple + printer driver for ppdev. Firstly we will + use the write function, and after that we + will drive the control and data lines directly. + -The first thing to do is to actually open the device. + + The first thing to do is to actually open the device. + - + ]]> -Here name should be something along the lines -of "/dev/parport0". (If you don't have any -/dev/parport files, you can make them with -mknod; they are character special device nodes with -major 99.) + + Here name should be something along the lines + of "/dev/parport0". (If you don't have any + /dev/parport files, you can make them with + mknod; they are character special device nodes + with major 99.) + -In order to do anything with the port we need to claim access to -it. + + In order to do anything with the port we need to claim access to + it. + - + ]]> -Our printer driver will copy its input (from -stdin) to the printer, and it can do that it one of -two ways. The first way is to hand it all off to the kernel driver, -with the knowledge that the protocol that the printer speaks is IEEE -1284's compatibility mode. + + Our printer driver will copy its input (from + stdin) to the printer, and it can do that it + one of two ways. The first way is to hand it all off to the + kernel driver, with the knowledge that the protocol that the + printer speaks is IEEE 1284's compatibility + mode. + - + ]]> -The write_printer function is not pictured -above. This is because the main loop that is shown can be used for -both methods of driving the printer. Here is one implementation of -write_printer: + + The write_printer function is not pictured + above. This is because the main loop that is shown can be used + for both methods of driving the printer. Here is one + implementation of write_printer: + - + ]]> + + + We hand the data to the kernel-level driver (using + write) and it handles the printer + protocol. + + + + Now let's do it the hard way! In this particular example there is + no practical reason to do anything other than just call + write, because we know that the printer talks + an IEEE 1284 protocol. On the other hand, this particular example + does not even need a user-land driver since there is already a + kernel-level one; for the purpose of this discussion, try to + imagine that the printer speaks a protocol that is not already + implemented under Linux. + -We hand the data to the kernel-level driver (using -write) and it handles the printer -protocol. - -Now let's do it the hard way! In this particular example there -is no practical reason to do anything other than just call -write, because we know that the printer talks an -IEEE 1284 protocol. On the other hand, this particular example does -not even need a user-land driver since there is already a kernel-level -one; for the purpose of this discussion, try to imagine that the -printer speaks a protocol that is not already implemented under -Linux. - -So, here is the alternative implementation of -write_printer (for brevity, error checking has -been omitted): + + So, here is the alternative implementation of + write_printer (for brevity, error checking + has been omitted): + - + ]]> -To show a bit more of the ppdev interface, -here is a small piece of code that is intended to mimic the printer's -side of printer protocol. + + To show a bit more of the ppdev interface, + here is a small piece of code that is intended to mimic the + printer's side of printer protocol. + - + ]]> + + + And here is an example (with no error checking at all) to show how + to read data from the port, using ECP mode, with optional + negotiation to ECP mode first. + + + + + + + - + + + API reference + + +!Fdrivers/parport/daisy.c parport_device_num +!Fdrivers/parport/daisy.c parport_device_coords +!Fdrivers/parport/daisy.c parport_find_device +!Fdrivers/parport/daisy.c parport_find_class +!Fdrivers/parport/share.c parport_register_driver +!Fdrivers/parport/share.c parport_unregister_driver +!Fdrivers/parport/share.c parport_register_device +!Fdrivers/parport/share.c parport_unregister_device +!Fdrivers/parport/daisy.c parport_open +!Fdrivers/parport/daisy.c parport_close +!Fdrivers/parport/share.c parport_claim +!Fdrivers/parport/share.c parport_claim_or_block +!Fdrivers/parport/share.c parport_release +!Finclude/linux/parport.h parport_yield +!Finclude/linux/parport.h parport_yield_blocking +!Fdrivers/parport/ieee1284.c parport_negotiate +!Fdrivers/parport/ieee1284.c parport_write +!Fdrivers/parport/ieee1284.c parport_read +!Fdrivers/parport/ieee1284.c parport_set_timeout + + + + + + The Linux 2.2 Parallel Port Subsystem + + + + Although the interface described in this document is largely new + with the 2.4 kernel, the sharing mechanism is available in the 2.2 + kernel as well. The functions available in 2.2 are: + + + + + + parport_register_device + + + + + + parport_unregister_device + + + + + + parport_claim + + + + + + parport_claim_or_block + + + + + + parport_release + + + + + + parport_yield + + + + + + parport_yield_blocking + + + + + + In addition, negotiation to reverse nibble mode is supported: + + + + + int parport_ieee1284_nibble_mode_ok + struct parport *port + unsigned char mode + + + + + The only valid values for mode are 0 (for + reverse nibble mode) and 4 (for Device ID in reverse nibble mode). + + + + This function is obsoleted by + parport_negotiate in Linux 2.4, and has been + removed. + + + + + + + + -
- \ No newline at end of file diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/filesystems/cramfs.txt linux/Documentation/filesystems/cramfs.txt --- v2.3.99-pre8/linux/Documentation/filesystems/cramfs.txt Fri Jan 21 18:19:15 2000 +++ linux/Documentation/filesystems/cramfs.txt Sat May 20 11:30:31 2000 @@ -27,8 +27,8 @@ mkcramfs simply truncates to 8 bits, which is a potential security issue. -Hard links are not supported, but symlinks are. (See also the TODO -comment in mkcramfs.c at the nlink test.) +Hard links are supported, but hard linked files +will still have a link count of 1 in the cramfs image. Cramfs directories have no `.' or `..' entries. Directories (like every other file on cramfs) always have a link count of 1. (There's diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/kbuild/config-language.txt linux/Documentation/kbuild/config-language.txt --- v2.3.99-pre8/linux/Documentation/kbuild/config-language.txt Thu May 11 15:30:05 2000 +++ linux/Documentation/kbuild/config-language.txt Sun May 21 20:18:08 2000 @@ -193,7 +193,7 @@ Configure: implemented Menuconfig: implemented -Xconfig: does not display, but writes to output files +Xconfig: implemented mconfig: implemented Example: diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/kernel-doc-nano-HOWTO.txt linux/Documentation/kernel-doc-nano-HOWTO.txt --- v2.3.99-pre8/linux/Documentation/kernel-doc-nano-HOWTO.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/kernel-doc-nano-HOWTO.txt Sun May 21 20:18:07 2000 @@ -0,0 +1,128 @@ +kernel-doc nano-HOWTO +===================== + +Many places in the source tree have extractable documentation in the +form of block comments above functions. The components of this system +are: + +- scripts/kernel-doc + + This is a perl script that hunts for the block comments and can mark + them up directly into DocBook, man, text, and HTML. (No, not + texinfo.) + +- Documentation/DocBook/*.tmpl + + These are SGML template files, which are normal SGML files with + special place-holders for where the extracted documentation should + go. + +- scripts/docproc.c + + This is a program for converting SGML template files into SGML + files. It invokes kernel-doc, giving it the list of functions that + are to be documented. + +- scripts/gen-all-syms + + This is a script that lists the EXPORT_SYMBOL symbols in a list of C + files. + +- scripts/docgen + + This script invokes docproc, telling it which functions are to be + documented (this list comes from gen-all-syms). + +- Makefile + + The targets 'sgmldocs', 'psdocs', and 'pdfdocs' are used to build + DocBook files, PostScript files, and PDF files in + Documentation/DocBook. + +- Documentation/DocBook/Makefile + + This is where C files are associated with SGML templates. + + +How to extract the documentation +-------------------------------- + +If you just want to read the ready-made books on the various +subsystems (see Documentation/DocBook/*.tmpl), just type 'make +psdocs', or 'make pdfdocs', depending on your preference. If you +would rather read a different format, you can type 'make sgmldocs' and +then use DocBook tools to convert Documentation/DocBook/*.sgml to a +format of your choice (for example, 'db2html ...'). + +If you want to see man pages instead, you can do this: + +$ cd linux +$ scripts/kernel-doc -man $(find -name '*.c') | split-man.pl /tmp/man + +Here is split-man.pl: + +--> +#!/usr/bin/perl + +if ($#ARGV < 0) { + die "where do I put the results?\n"; +} + +mkdir $ARGV[0],0777 or die "Can't create $ARGV[0]: $!\n"; +$state = 0; +while () { + if (/^\.TH \"[^\"]*\" 4 \"([^\"]*)\"/) { + if ($state == 1) { close OUT } + $state = 1; + $fn = "$ARGV[0]/$1.4"; + print STDERR "Creating $fn\n"; + open OUT, ">$fn" or die "can't open $fn: $!\n"; + print OUT $_; + } elsif ($state != 0) { + print OUT $_; + } +} + +close OUT; +<-- + +If you just want to view the documentation for one function in one +file, you can do this: + +$ scripts/kernel-doc -man -function fn file | nroff -man | less + +or this: + +$ scripts/kernel-doc -text -function fn file + + +How to add extractable documentation to your source files +--------------------------------------------------------- + +The format of the block comment is like this: + +/** + * function_name(:)? (- short description)? +(* @parameterx: (description of parameter x)?)* +(* a blank line)? + * (Description:)? (Description of function)? + * (section header: (section description)? )* +(*)?*/ + +The short function description cannot be multiline, but the other +descriptions can be. + +All descriptive text is further processed, scanning for the following special +patterns, which are highlighted appropriately. + +'funcname()' - function +'$ENVVAR' - environment variable +'&struct_name' - name of a structure (up to two words including 'struct') +'@parameter' - name of a parameter +'%CONST' - name of a constant. + +Take a look around the source tree for examples. + +Tim. +*/ + diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/networking/8139too.txt linux/Documentation/networking/8139too.txt --- v2.3.99-pre8/linux/Documentation/networking/8139too.txt Thu May 11 15:30:05 2000 +++ linux/Documentation/networking/8139too.txt Sat May 20 11:38:02 2000 @@ -132,6 +132,20 @@ +Submitting Bug Reports +---------------------- +Obtain and compile the modified rtl8139-diag source code from the +8139too driver Web site. This diagnostics programs, originally +from Donald Becker, has been modified to display all registers +on your RTL8139 chip, not just the first 0x80. + +If possible, send the output of a working and broken driver with + rtl8139-diag -mmmaaavvveefN > my-output-file.txt + +Send "lspci -vvv" or "cat /proc/pci" output for PCI information. + + + Known Bugs / Errata / To-Do --------------------------- The following issues are known, and are actively being pursued. Patches @@ -149,7 +163,7 @@ 4) Sparc64 platform not tested at all. -5) Identify and fix "rx wedge" when ping flooded. +5) Identify and fix "rx wedge" when ping flooded. (WIP) 7) N-Way auto-negotiation is known to fail in some cases. This problem also occurs in the rtl8139 driver in kernels 2.2.x/2.3.x. Solution: @@ -158,17 +172,30 @@ it automatically. (patches welcome) 8) Much improved command line / module parameter setup. (patches and -suggestions welcome) +suggestions welcome) (WIP) 9) Better documentation. (patches welcome) -10) User-mode (or maybe optional /proc) diagnostics program. +10) (rtl8139-diag modified from Becker version, DONE) +User-mode (or maybe optional /proc) diagnostics program. + +11) RTL8139C support untested. Change History -------------- +Version 0.9.5 - May 17, 2000 + +* Improved chip version recognition +* Continue banging away at receiver hang problem +* Use spin_lock_irq in another spot +* Don't print anything on pci_enable_device, it does so for us +* Disable buggy NWay code +* Define TxConfig bitmasks + + Version 0.9.4.1 - April 27, 2000 - third public beta release * Replace several "magic numbers" with symbolic constants diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/pci.txt linux/Documentation/pci.txt --- v2.3.99-pre8/linux/Documentation/pci.txt Thu May 11 15:30:05 2000 +++ linux/Documentation/pci.txt Mon May 15 12:13:10 2000 @@ -89,6 +89,16 @@ function otherwise. __devexit The same for __exit. +Tips: + The module_init()/module_exit() functions (and all initialization + functions called only from these) should be marked __init/exit. + The struct pci_driver shouldn't be marked with any of these tags. + The ID table array should be marked __devinitdata. + The probe() and remove() functions (and all initialization + functions called only from these) should be marked __devinit/exit. + If you are sure the driver is not a hotplug driver then use only + __init/exit __initdata/exitdata. + 2. How to find PCI devices manually (the old style) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/s390/DASD linux/Documentation/s390/DASD --- v2.3.99-pre8/linux/Documentation/s390/DASD Fri May 12 14:18:55 2000 +++ linux/Documentation/s390/DASD Sat May 20 11:30:31 2000 @@ -22,7 +22,7 @@ support of the FBA and CKD architectures. For the FBA architecture only some smart data structures are missing to make the support complete. -We performed our testing on 3380 and 3390 type disksof different +We performed our testing on 3380 and 3390 type disks of different sizes, under VM and on the bare hardware (LPAR), using internal disks of the multiprise as well as a RAMAC virtual array. Disks exported by an Enterprise Storage Server (Seascape) should work fine as well. diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt --- v2.3.99-pre8/linux/Documentation/usb/ov511.txt Thu May 11 15:30:05 2000 +++ linux/Documentation/usb/ov511.txt Sat May 20 10:37:04 2000 @@ -6,11 +6,8 @@ Homepage: http://alpha.dyndns.org/ov511 NEW IN THIS VERSION: - o Improvements to sensor detection code - o Added "i2c_detect_tries" and "aperture" parameters - o proc filesystem status support - o read() fixed partially - o code cleanups and minor fixes + o 352x288 mode + o force_rgb parameter for apps that expect RGB instead of BGR INTRODUCTION: @@ -139,7 +136,7 @@ or so lines higher than the red component. This is only apparent in images with white objects on black backgrounds at 640x480. Setting this to 1 will realign the color planes correctly. NOTE: This is still - experimental and very buggy. + experimental and very buggy. You will likely need a fast (500 Mhz) CPU. NAME: snapshot TYPE: integer (boolean) @@ -148,8 +145,41 @@ button is pressed. Note that this does not yet work with most apps, including xawtv and vidcat. NOTE: See the section "TODO" for more info. + NAME: sensor + TYPE: integer ([0, 1, 3]) + DEFAULT: [varies] + DESC: If you know that your camera sensor is not detected correctly, set this + parameter. This is a global option for all attached OV511 cameras. You + will probably never need to set this, but if you do, valid values are: + 0 for OV7620 + 1 for OV7620AE + 3 for OV7610 + + NAME: i2c_detect_tries + TYPE: integer (don't set it insanely high!) + DEFAULT: 5 + DESC: This is the number of times the driver will try to sync and detect the + internal i2c bus (which connects the OV511 and sensor). If you are + getting intermittant detection failures ("Failed to read sensor ID...") + you should increase this by a modest amount. If setting it to 20 or so + doesn't fix things, look elsewhere for the cause of the problem. + + NAME: aperture + TYPE: integer (0 - 15) + DEFAULT: [varies by sensor] + DESC: For legal values, see the OV7610/7620 specs under register Common F. + This setting affects the upper nybble of that reg (bits 4-7). This is + for if you want to play with the camera's pixel saturation. + + NAME: force_rgb + TYPE: integer (boolean) + DEFAULT: 0 + DESC: Force image to be read in RGB instead of BGR. This option allow + programs that expect RGB data (e.g. gqcam) to work with this driver. If + your colors look VERY wrong, you may want to change this. + WORKING FEATURES: - o Color streaming/capture at 640x480 and 320x240 + o Color streaming/capture at 640x480, 352x288, and 320x240 o YUV420 color o Monochrome o Setting/getting of saturation, contrast and brightness (no hue yet; only @@ -158,7 +188,7 @@ EXPERIMENTAL FEATURES: o fix_rgb_offset: Sometimes works, but other times causes errors with xawtv and - corrupted frames. + corrupted frames. If you have a very fast CPU, you can try it. o Snapshot mode (only works with some read() based apps; see below for more) o read() support @@ -197,6 +227,6 @@ The code is based in no small part on the CPiA driver by Johannes Erdfelt, Randy Dunlap, and others. Big thanks to them for their pioneering work on that -and the USB stack. Thanks to Bret Wallach for getting camera reg IO , ISOC, and -image capture working. Thanks to Orion Sky Lawlor and Kevin Moore for their -work as well. +and the USB stack. Thanks to Bret Wallach for getting camera reg IO, ISOC, and +image capture working. Thanks to Orion Sky Lawlor, Kevin Moore, and Claudio +Matsuoka for their work as well. diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt --- v2.3.99-pre8/linux/Documentation/usb/usb-serial.txt Thu May 11 15:30:05 2000 +++ linux/Documentation/usb/usb-serial.txt Sat May 20 11:39:56 2000 @@ -59,6 +59,13 @@ properly enumerated, assigned a port, and then communication _should_ be possible. The driver cleans up properly when the device is removed, or the connection is canceled on the Visor. + + NOTE: + This means that in order to talk to the Visor, the sync button must be + pressed BEFORE trying to get any program to communicate to the Visor. + This goes against the current documentation for pilot-xfer and other + packages, but is the only way that it will work due to the hardware + in the Visor. When the device is connected, try talking to it on the second port (this is usually /dev/ttyUSB1 if you do not have any other usb-serial @@ -105,6 +112,24 @@ This is an ISDN TA. Please report both successes and troubles to the author at omninet@kroah.com + + +Digi AccelePort Driver + + This driver supports the Digi AccelePort USB 4 device, a 4 port + USB serial converter. The driver does NOT yet support the Digi + AccelePort USB 2 or 8. + + The driver supports open, close, read, write, termios settings (baud + rate, word size, parity, stop bits, hardware/software flow control, + CREAD), DTR/RTS, and TIOCMGET/SET/BIS/BIC ioctls. It has not been + thoroughly tested, but it seems to be working reasonable well. There + is more work to do, including flow control, ioctls, and support for + the Digi AccelePort USB 2 and 8. + + Please contact Peter Berger (pberger@brimson.com) or Al Borchers + (alborchers@steinerpoint.com) for questions or problems with this + driver. Generic Serial driver diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/video4linux/bttv/CARDLIST linux/Documentation/video4linux/bttv/CARDLIST --- v2.3.99-pre8/linux/Documentation/video4linux/bttv/CARDLIST Tue Apr 11 15:09:11 2000 +++ linux/Documentation/video4linux/bttv/CARDLIST Mon May 15 12:06:25 2000 @@ -38,6 +38,10 @@ card=36 - Typhoon TView TV/FM Tuner card=37 - PixelView PlayTV pro card=38 - TView99 CPH063 + card=39 - Pinnacle PCTV Rave + card=40 - STB2 + card=41 - AVerMedia TVPhone 98 + card=42 - ProVideo PV951 tuner.o type=0 - Temic PAL diff -u --recursive --new-file v2.3.99-pre8/linux/MAINTAINERS linux/MAINTAINERS --- v2.3.99-pre8/linux/MAINTAINERS Thu May 11 15:30:05 2000 +++ linux/MAINTAINERS Sat May 20 11:39:56 2000 @@ -482,6 +482,7 @@ IDE DRIVER [GENERAL] P: Andre Hedrick M: andre@linux-ide.org +M: ahedrick@atipa.com M: andre@suse.com L: linux-kernel@vger.rutgers.edu W: http://www.kernel.org/pub/linux/kernel/people/hedrick/ @@ -1139,6 +1140,13 @@ L: linux-usb@suse.com S: Maintained +USB OV511 DRIVER +P: Mark McClelland +M: mmcclelland@delphi.com +L: linux-usb@suse.com +W: http://alpha.dyndns.org/ov511/ +S: Maintained + USB PEGASUS DRIVER P: Petko Manolov M: petkan@spct.net @@ -1148,6 +1156,13 @@ USB PRINTER DRIVER P: Vojtech Pavlik M: vojtech@suse.cz +L: linux-usb@suse.com +S: Supported + +USB SERIAL DIGI ACCELEPORT DRIVER +P: Peter Berger and Al Borchers +M: pberger@brimson.com +M: alborchers@steinerpoint.com L: linux-usb@suse.com S: Supported diff -u --recursive --new-file v2.3.99-pre8/linux/Makefile linux/Makefile --- v2.3.99-pre8/linux/Makefile Fri May 12 14:18:55 2000 +++ linux/Makefile Mon May 15 15:30:20 2000 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 3 SUBLEVEL = 99 -EXTRAVERSION = -pre8 +EXTRAVERSION = -pre9 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -81,10 +81,6 @@ # CPPFLAGS := -D__KERNEL__ -I$(HPATH) - -ifdef CONFIG_SMP -CPPFLAGS += -D__SMP__ -endif CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.3.99-pre8/linux/arch/alpha/kernel/osf_sys.c Thu May 11 15:30:05 2000 +++ linux/arch/alpha/kernel/osf_sys.c Sat May 20 10:47:29 2000 @@ -42,7 +42,6 @@ #include #include -extern long do_sys_mount(char *, char *, char *, int, void *); extern int do_pipe(int *); extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags); @@ -377,7 +376,7 @@ retval = PTR_ERR(devname); if (IS_ERR(devname)) goto out; - retval = do_sys_mount(devname, dirname, "ext2", flags, NULL); + retval = do_mount(devname, dirname, "ext2", flags, NULL); putname(devname); out: return retval; @@ -396,7 +395,7 @@ retval = PTR_ERR(devname); if (IS_ERR(devname)) goto out; - retval = do_sys_mount(devname, dirname, "iso9660", flags, NULL); + retval = do_mount(devname, dirname, "iso9660", flags, NULL); putname(devname); out: return retval; @@ -409,7 +408,7 @@ if (copy_from_user(&tmp, args, sizeof(tmp))) return -EFAULT; - return do_sys_mount("", dirname, "proc", flags, NULL); + return do_mount("", dirname, "proc", flags, NULL); } asmlinkage int osf_mount(unsigned long typenr, char *path, int flag, void *data) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/Makefile linux/arch/arm/Makefile --- v2.3.99-pre8/linux/arch/arm/Makefile Fri May 12 14:18:55 2000 +++ linux/arch/arm/Makefile Mon May 15 12:00:34 2000 @@ -182,7 +182,7 @@ SUBDIRS += drivers/acorn DRIVERS += drivers/acorn/block/acorn-block.a DRIVERS += drivers/acorn/char/acorn-char.o -DRIVERS += drivers/acorn/net/acorn-net.a +DRIVERS += drivers/acorn/net/acorn-net.o DRIVERS += drivers/acorn/scsi/acorn-scsi.a endif diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/def-configs/ebsa110 linux/arch/arm/def-configs/ebsa110 --- v2.3.99-pre8/linux/arch/arm/def-configs/ebsa110 Thu May 11 15:30:05 2000 +++ linux/arch/arm/def-configs/ebsa110 Mon May 15 12:00:33 2000 @@ -10,7 +10,7 @@ CONFIG_EXPERIMENTAL=y # -# System and processor type +# System and Processor Type # # CONFIG_ARCH_ARC is not set # CONFIG_ARCH_A5K is not set @@ -25,6 +25,8 @@ # CONFIG_PCI is not set # CONFIG_ISA is not set # CONFIG_ISA_DMA is not set +# CONFIG_SBUS is not set +# CONFIG_PCMCIA is not set # # Loadable module support @@ -69,7 +71,6 @@ # I2O device support # # CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set # CONFIG_I2O_BLOCK is not set # CONFIG_I2O_LAN is not set # CONFIG_I2O_SCSI is not set @@ -87,13 +88,19 @@ # CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set # # Additional Block Devices # # CONFIG_BLK_DEV_LOOP is not set CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_RAID15_DANGEROUS is not set CONFIG_BLK_DEV_RAM=y # CONFIG_BLK_DEV_INITRD is not set @@ -124,7 +131,7 @@ # Mice # # CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y +# CONFIG_MOUSE is not set # CONFIG_PSMOUSE is not set # CONFIG_82C710_MOUSE is not set # CONFIG_PC110_PAD is not set @@ -141,6 +148,7 @@ CONFIG_WATCHDOG=y # CONFIG_WATCHDOG_NOWAYOUT is not set # CONFIG_WDT is not set +# CONFIG_WDTPCI is not set CONFIG_SOFT_WATCHDOG=y # CONFIG_PCWATCHDOG is not set # CONFIG_ACQUIRE_WDT is not set @@ -173,6 +181,7 @@ CONFIG_RTNETLINK=y # CONFIG_NETLINK_DEV is not set CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y @@ -222,6 +231,7 @@ CONFIG_IP_NF_TARGET_REJECT=y # CONFIG_IP_NF_TARGET_MIRROR is not set CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_IP_NF_TARGET_REDIRECT=y CONFIG_IP_NF_MANGLE=y @@ -302,10 +312,12 @@ # CONFIG_HIPPI is not set # CONFIG_PLIP is not set CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set CONFIG_PPP_ASYNC=y # CONFIG_PPP_SYNC_TTY is not set CONFIG_PPP_DEFLATE=m CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m # CONFIG_SLIP is not set # @@ -342,9 +354,10 @@ # File systems # # CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS_FS is not set CONFIG_AUTOFS4_FS=y # CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set @@ -354,10 +367,12 @@ # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set -CONFIG_MINIX_FS=y +# CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set @@ -365,23 +380,39 @@ # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set # CONFIG_EXT2_FS is not set # CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/def-configs/footbridge linux/arch/arm/def-configs/footbridge --- v2.3.99-pre8/linux/arch/arm/def-configs/footbridge Thu May 11 15:30:05 2000 +++ linux/arch/arm/def-configs/footbridge Mon May 15 12:00:33 2000 @@ -10,7 +10,7 @@ CONFIG_EXPERIMENTAL=y # -# System and processor type +# System and Processor Type # # CONFIG_ARCH_ARC is not set # CONFIG_ARCH_A5K is not set @@ -19,6 +19,10 @@ CONFIG_FOOTBRIDGE=y CONFIG_HOST_FOOTBRIDGE=y # CONFIG_ADDIN_FOOTBRIDGE is not set + +# +# Footbridge Implementations +# CONFIG_ARCH_EBSA285=y # CONFIG_ARCH_CATS is not set CONFIG_ARCH_NETWINDER=y @@ -30,7 +34,10 @@ CONFIG_CPU_SA110=y CONFIG_PCI=y CONFIG_PCI_NAMES=y +CONFIG_ISA=y CONFIG_ISA_DMA=y +# CONFIG_SBUS is not set +# CONFIG_PCMCIA is not set CONFIG_ALIGNMENT_TRAP=y # @@ -137,7 +144,11 @@ # CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_RAID15_DANGEROUS is not set CONFIG_BLK_DEV_RAM=y # CONFIG_BLK_DEV_INITRD is not set @@ -202,6 +213,7 @@ CONFIG_WATCHDOG=y # CONFIG_WATCHDOG_NOWAYOUT is not set # CONFIG_WDT is not set +# CONFIG_WDTPCI is not set CONFIG_SOFT_WATCHDOG=y # CONFIG_PCWATCHDOG is not set # CONFIG_ACQUIRE_WDT is not set @@ -242,6 +254,7 @@ # CONFIG_VIDEO_PMS is not set # CONFIG_VIDEO_BWQCAM is not set # CONFIG_VIDEO_CQCAM is not set +# CONFIG_VIDEO_CPIA is not set # CONFIG_VIDEO_SAA5249 is not set # CONFIG_TUNER_3036 is not set # CONFIG_VIDEO_STRADIS is not set @@ -262,56 +275,6 @@ # CONFIG_AGP is not set # -# USB support -# -CONFIG_USB=m - -# -# USB Controllers -# -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -CONFIG_USB_OHCI=m - -# -# Miscellaneous USB options -# -# CONFIG_USB_DEVICEFS is not set - -# -# USB Devices -# -CONFIG_USB_PRINTER=m -CONFIG_USB_SCANNER=m -CONFIG_USB_AUDIO=m -# CONFIG_USB_ACM is not set -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_CPIA is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_USS720 is not set -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_PLUSB is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_DSBR is not set - -# -# USB HID -# -# CONFIG_USB_HID is not set -CONFIG_USB_KBD=m -CONFIG_USB_MOUSE=m -# CONFIG_USB_WACOM is not set -# CONFIG_USB_WMFORCE is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set - -# # Console drivers # CONFIG_VGA_CONSOLE=y @@ -522,10 +485,12 @@ # CONFIG_HIPPI is not set # CONFIG_PLIP is not set CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set CONFIG_PPP_ASYNC=m # CONFIG_PPP_SYNC_TTY is not set CONFIG_PPP_DEFLATE=m CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m CONFIG_SLIP=m CONFIG_SLIP_COMPRESSED=y CONFIG_SLIP_SMART=y @@ -588,9 +553,10 @@ CONFIG_IDEDMA_PCI_EXPERIMENTAL=y # CONFIG_IDEDMA_PCI_WIP is not set # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set -# CONFIG_BLK_DEV_AEC6210 is not set -# CONFIG_AEC6210_TUNING is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_AEC62XX_TUNING is not set # CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_WDC_ALI15X3 is not set # CONFIG_BLK_DEV_AMD7409 is not set # CONFIG_AMD7409_OVERRIDE is not set # CONFIG_BLK_DEV_CMD64X is not set @@ -610,6 +576,7 @@ # CONFIG_BLK_DEV_SIS5513 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_VIA82CXXX_TUNING is not set CONFIG_BLK_DEV_SL82C105=y # CONFIG_IDE_CHIPSETS is not set CONFIG_IDEDMA_AUTO=y @@ -625,6 +592,7 @@ # CONFIG_SOUND=m # CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set # CONFIG_SOUND_ES1370 is not set # CONFIG_SOUND_ES1371 is not set # CONFIG_SOUND_ESSSOLO1 is not set @@ -633,6 +601,7 @@ # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set CONFIG_SOUND_OSS=m # CONFIG_SOUND_TRACEINIT is not set # CONFIG_SOUND_DMAP is not set @@ -643,6 +612,7 @@ # CONFIG_SOUND_CS4232 is not set # CONFIG_SOUND_SSCAPE is not set # CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_ICH is not set # CONFIG_SOUND_VMIDI is not set # CONFIG_SOUND_TRIX is not set # CONFIG_SOUND_MSS is not set @@ -657,7 +627,6 @@ # CONFIG_SOUND_AWE32_SYNTH is not set # CONFIG_SOUND_WAVEFRONT is not set # CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_VIA82CXXX is not set # CONFIG_SOUND_YM3812 is not set # CONFIG_SOUND_OPL3SA1 is not set # CONFIG_SOUND_OPL3SA2 is not set @@ -670,8 +639,8 @@ # File systems # # CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -# CONFIG_AUTOFS4_FS is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y CONFIG_ADFS_FS=m # CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set @@ -683,10 +652,12 @@ CONFIG_VFAT_FS=m # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set CONFIG_ISO9660_FS=m CONFIG_JOLIET=y # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set @@ -694,17 +665,22 @@ # CONFIG_DEVFS_DEBUG is not set CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y CONFIG_NFSD=m # CONFIG_NFSD_V3 is not set @@ -712,6 +688,16 @@ CONFIG_LOCKD=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types @@ -767,6 +753,57 @@ # CONFIG_NLS_KOI8_R is not set # +# USB support +# +CONFIG_USB=m +CONFIG_USB_DEBUG=y + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set + +# +# USB Controllers +# +# CONFIG_USB_UHCI is not set +# CONFIG_USB_UHCI_ALT is not set +CONFIG_USB_OHCI=m + +# +# USB Devices +# +CONFIG_USB_PRINTER=m +CONFIG_USB_SCANNER=m +CONFIG_USB_AUDIO=m +# CONFIG_USB_ACM is not set +# CONFIG_USB_SERIAL is not set +# CONFIG_USB_IBMCAM is not set +# CONFIG_USB_OV511 is not set +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_STORAGE is not set +# CONFIG_USB_USS720 is not set +# CONFIG_USB_DABUSB is not set +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_DSBR is not set + +# +# USB HID +# +# CONFIG_USB_HID is not set +CONFIG_USB_KBD=m +CONFIG_USB_MOUSE=m +# CONFIG_USB_WACOM is not set +# CONFIG_USB_WMFORCE is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# # Kernel hacking # CONFIG_FRAME_POINTER=y @@ -774,4 +811,5 @@ CONFIG_DEBUG_USER=y # CONFIG_DEBUG_INFO is not set CONFIG_MAGIC_SYSRQ=y -# CONFIG_DEBUG_LL is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_DC21285_PORT is not set diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/def-configs/rpc linux/arch/arm/def-configs/rpc --- v2.3.99-pre8/linux/arch/arm/def-configs/rpc Thu Feb 10 17:11:02 2000 +++ linux/arch/arm/def-configs/rpc Mon May 15 12:00:33 2000 @@ -2,6 +2,7 @@ # Automatically generated make config: don't edit # CONFIG_ARM=y +CONFIG_UID16=y # # Code maturity level options @@ -9,7 +10,7 @@ CONFIG_EXPERIMENTAL=y # -# System and processor type +# System and Processor Type # # CONFIG_ARCH_ARC is not set # CONFIG_ARCH_A5K is not set @@ -23,7 +24,11 @@ CONFIG_CPU_ARM6=y CONFIG_CPU_ARM7=y CONFIG_CPU_SA110=y +# CONFIG_PCI is not set +# CONFIG_ISA is not set # CONFIG_ISA_DMA is not set +# CONFIG_SBUS is not set +# CONFIG_PCMCIA is not set # CONFIG_ALIGNMENT_TRAP is not set # @@ -47,10 +52,14 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_ARTHUR is not set + +# +# Parallel port support +# CONFIG_PARPORT=y CONFIG_PARPORT_PC=y # CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_PCMCIA is not set +CONFIG_PARPORT_PC_SUPERIO=y # CONFIG_PARPORT_ARC is not set # CONFIG_PARPORT_AMIGA is not set # CONFIG_PARPORT_MFC3 is not set @@ -63,7 +72,6 @@ # I2O device support # # CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set # CONFIG_I2O_BLOCK is not set # CONFIG_I2O_LAN is not set # CONFIG_I2O_SCSI is not set @@ -79,44 +87,23 @@ # Block devices # CONFIG_BLK_DEV_FD=y -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -CONFIG_BLK_DEV_IDE_ICSIDE=y -CONFIG_BLK_DEV_IDEDMA_ICS=y -CONFIG_IDEDMA_ICS_AUTO=y -CONFIG_BLK_DEV_IDE_RAPIDE=y -CONFIG_BLK_DEV_IDEDMA=y -CONFIG_IDEDMA_AUTO=y -# CONFIG_IDE_CHIPSETS is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set # # Additional Block Devices # CONFIG_BLK_DEV_LOOP=m # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_RAID15_DANGEROUS is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_INITRD=y -# CONFIG_BLK_DEV_XD is not set -CONFIG_PARIDE_PARPORT=y -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set # # Acorn-specific block devices @@ -139,6 +126,17 @@ # CONFIG_PPDEV is not set # +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_PHILIPSPAR is not set +# CONFIG_I2C_ELV is not set +# CONFIG_I2C_VELLEMAN is not set +# CONFIG_I2C_ALGOPCF is not set +CONFIG_I2C_CHARDEV=y + +# # Mice # CONFIG_BUSMOUSE=y @@ -177,20 +175,10 @@ # CONFIG_FTAPE is not set # CONFIG_DRM is not set # CONFIG_DRM_TDFX is not set - -# -# PCMCIA character device support -# -# CONFIG_PCMCIA_SERIAL_CS is not set # CONFIG_AGP is not set CONFIG_RPCMOUSE=y # -# Support for USB -# -# CONFIG_USB is not set - -# # Console drivers # CONFIG_FB=y @@ -201,10 +189,6 @@ CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y CONFIG_FB_ACORN=y -# CONFIG_FB_MATROX is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_3DFX is not set # CONFIG_FB_VIRTUAL is not set CONFIG_FBCON_ADVANCED=y CONFIG_FBCON_MFB=y @@ -222,6 +206,7 @@ # CONFIG_FBCON_MAC is not set # CONFIG_FBCON_VGA_PLANES is not set # CONFIG_FBCON_VGA is not set +# CONFIG_FBCON_HGA is not set # CONFIG_FBCON_FONTWIDTH8_ONLY is not set CONFIG_FBCON_FONTS=y # CONFIG_FONT_8x8 is not set @@ -298,6 +283,7 @@ # # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set +# CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_NET_SB1000 is not set @@ -312,12 +298,10 @@ # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_RTL8139 is not set -# CONFIG_DM9102 is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set -# CONFIG_NET_EISA is not set +# CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set # @@ -330,10 +314,12 @@ # CONFIG_HIPPI is not set # CONFIG_PLIP is not set CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set # CONFIG_PPP_ASYNC is not set # CONFIG_PPP_SYNC_TTY is not set # CONFIG_PPP_DEFLATE is not set # CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m # CONFIG_SLIP is not set # @@ -342,7 +328,7 @@ # CONFIG_NET_RADIO is not set # -# Token Ring driver support +# Token Ring devices # # CONFIG_TR is not set # CONFIG_NET_FC is not set @@ -355,9 +341,42 @@ # CONFIG_WAN is not set # -# PCMCIA network device support +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices # -# CONFIG_NET_PCMCIA is not set +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_BLK_DEV_IDECS is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +CONFIG_BLK_DEV_IDE_ICSIDE=y +CONFIG_BLK_DEV_IDEDMA_ICS=y +CONFIG_IDEDMA_ICS_AUTO=y +CONFIG_BLK_DEV_IDEDMA=y +CONFIG_BLK_DEV_IDE_RAPIDE=y +# CONFIG_IDE_CHIPSETS is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_BLK_DEV_IDE_MODES is not set # # SCSI support @@ -368,9 +387,11 @@ # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set +CONFIG_SD_EXTRA_DEVS=8 +CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_SR_EXTRA_DEVS=2 CONFIG_CHR_DEV_SG=y # @@ -390,12 +411,12 @@ # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_IPS is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA is not set # CONFIG_SCSI_EATA_DMA is not set @@ -403,6 +424,8 @@ # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set CONFIG_SCSI_PPA=m CONFIG_SCSI_IMM=m # CONFIG_SCSI_IZIP_EPP16 is not set @@ -410,15 +433,14 @@ # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_PSI240I is not set # CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SEAGATE is not set # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set # CONFIG_SCSI_DEBUG is not set CONFIG_SCSI_ACORNSCSI_3=m CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE=y @@ -439,6 +461,7 @@ # CONFIG_SOUND=m # CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set # CONFIG_SOUND_ES1370 is not set # CONFIG_SOUND_ES1371 is not set # CONFIG_SOUND_ESSSOLO1 is not set @@ -447,12 +470,18 @@ # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set CONFIG_SOUND_OSS=m +# CONFIG_SOUND_TRACEINIT is not set +# CONFIG_SOUND_DMAP is not set # CONFIG_SOUND_AD1816 is not set # CONFIG_SOUND_SGALAXY is not set +# CONFIG_SOUND_ADLIB is not set +# CONFIG_SOUND_ACI_MIXER is not set # CONFIG_SOUND_CS4232 is not set # CONFIG_SOUND_SSCAPE is not set # CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_ICH is not set # CONFIG_SOUND_VMIDI is not set # CONFIG_SOUND_TRIX is not set # CONFIG_SOUND_MSS is not set @@ -460,30 +489,29 @@ # CONFIG_SOUND_NM256 is not set # CONFIG_SOUND_MAD16 is not set # CONFIG_SOUND_PAS is not set +# CONFIG_PAS_JOYSTICK is not set # CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_SOFTOSS is not set +CONFIG_SOUND_SOFTOSS=m # CONFIG_SOUND_SB is not set +# CONFIG_SOUND_AWE32_SYNTH is not set # CONFIG_SOUND_WAVEFRONT is not set # CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_VIA82CXXX is not set # CONFIG_SOUND_YM3812 is not set # CONFIG_SOUND_OPL3SA1 is not set # CONFIG_SOUND_OPL3SA2 is not set # CONFIG_SOUND_UART6850 is not set +# CONFIG_SOUND_AEDSP16 is not set CONFIG_SOUND_VIDC=m # CONFIG_SOUND_WAVEARTIST is not set # -# Additional low level sound drivers -# -# CONFIG_LOWLEVEL_SOUND is not set - -# -# Filesystems +# File systems # # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=m CONFIG_ADFS_FS=y +# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set @@ -492,35 +520,66 @@ # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set CONFIG_ISO9660_FS=y CONFIG_JOLIET=y # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +# CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_ROOT_NFS is not set # CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types # CONFIG_PARTITION_ADVANCED=y +CONFIG_ACORN_PARTITION=y +CONFIG_ACORN_PARTITION_ICS=y +CONFIG_ACORN_PARTITION_ADFS=y +CONFIG_ACORN_PARTITION_POWERTEC=y +CONFIG_ACORN_PARTITION_RISCIX=y CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +# CONFIG_ATARI_PARTITION is not set CONFIG_MAC_PARTITION=y CONFIG_MSDOS_PARTITION=y CONFIG_BSD_DISKLABEL=y @@ -528,13 +587,6 @@ # CONFIG_UNIXWARE_DISKLABEL is not set CONFIG_SGI_PARTITION=y CONFIG_SUN_PARTITION=y -CONFIG_AMIGA_PARTITION=y -# CONFIG_ATARI_PARTITION is not set -CONFIG_ACORN_PARTITION=y -CONFIG_ACORN_PARTITION_ADFS=y -CONFIG_ACORN_PARTITION_ICS=y -CONFIG_ACORN_PARTITION_POWERTEC=y -CONFIG_ACORN_PARTITION_RISCIX=y CONFIG_NLS=y # @@ -568,6 +620,11 @@ # CONFIG_NLS_ISO8859_14 is not set # CONFIG_NLS_ISO8859_15 is not set CONFIG_NLS_KOI8_R=m + +# +# USB support +# +# CONFIG_USB is not set # # Kernel hacking diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile --- v2.3.99-pre8/linux/arch/arm/kernel/Makefile Fri May 12 14:18:55 2000 +++ linux/arch/arm/kernel/Makefile Mon May 15 12:00:33 2000 @@ -34,7 +34,7 @@ export-objs := armksyms.o dma.o ecard.o hw-footbridge.o leds-$(MACHINE).o -obj-$(CONFIG_ARCH_ACORN) += dma.o ecard.o iic.o fiq.o time-acorn.o +obj-$(CONFIG_ARCH_ACORN) += dma.o ecard.o fiq.o time-acorn.o obj-$(CONFIG_DEBUG_LL) += debug-$(PROCESSOR).o obj-$(CONFIG_MODULES) += armksyms.o obj-$(CONFIG_LEDS) += leds-$(MACHINE).o diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/kernel/iic.c linux/arch/arm/kernel/iic.c --- v2.3.99-pre8/linux/arch/arm/kernel/iic.c Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/kernel/iic.c Wed Dec 31 16:00:00 1969 @@ -1,248 +0,0 @@ -/* - * linux/arch/arm/kernel/iic.c - * - * Copyright (C) 1995, 1996 Russell King - * - * IIC is used to get the current time from the CMOS rtc. - */ - -#include -#include - -#include -#include -#include -#include - -#define FORCE_ONES 0xdc - -/* - * if delay loop has been calibrated then us that, - * else use IOC timer 1. - */ -static void iic_delay(void) -{ - extern unsigned long loops_per_sec; - if (loops_per_sec != (1 << 12)) { - udelay(100); /* was 10 */ - return; - } else { - unsigned long flags; - save_flags_cli(flags); - - outb(254, IOC_T1LTCHL); - outb(255, IOC_T1LTCHH); - outb(0, IOC_T1GO); - outb(1<<6, IOC_IRQCLRA); /* clear T1 irq */ - outb(10, IOC_T1LTCHL); /* was 4 */ - outb(0, IOC_T1LTCHH); - outb(0, IOC_T1GO); - while ((inb(IOC_IRQSTATA) & (1<<6)) == 0); - restore_flags(flags); - } -} - -#define IIC_INIT() dat = (inb(IOC_CONTROL) | FORCE_ONES) & ~3 -#define IIC_SET_DAT outb(dat|=1, IOC_CONTROL); -#define IIC_CLR_DAT outb(dat&=~1, IOC_CONTROL); -#define IIC_SET_CLK outb(dat|=2, IOC_CONTROL); -#define IIC_CLR_CLK outb(dat&=~2, IOC_CONTROL); -#define IIC_DELAY iic_delay(); -#define IIC_READ_DATA() (inb(IOC_CONTROL) & 1) - -static inline void iic_set_lines(int clk, int dat) -{ - int old; - - old = inb(IOC_CONTROL) | FORCE_ONES; - - old &= ~3; - - if (clk) - old |= 2; - if (dat) - old |= 1; - - outb(old, IOC_CONTROL); - - iic_delay(); -} - -static inline unsigned int iic_read_data(void) -{ - return inb(IOC_CONTROL) & 1; -} - -/* - * C: ==~~_ - * D: =~~__ - */ -static inline void iic_start(void) -{ - unsigned int dat; - - IIC_INIT(); - - IIC_SET_DAT - IIC_DELAY - IIC_SET_CLK - IIC_DELAY - - IIC_CLR_DAT - IIC_DELAY - IIC_CLR_CLK - IIC_DELAY -} - -/* - * C: __~~ - * D: =__~ - */ -static inline void iic_stop(void) -{ - unsigned int dat; - - IIC_INIT(); - - IIC_CLR_DAT - IIC_DELAY - IIC_SET_CLK - IIC_DELAY - IIC_SET_DAT - IIC_DELAY -} - -/* - * C: __~_ - * D: =___ - */ -static inline void iic_acknowledge(void) -{ - unsigned int dat; - - IIC_INIT(); - - IIC_CLR_DAT - IIC_DELAY - IIC_SET_CLK - IIC_DELAY - IIC_CLR_CLK - IIC_DELAY -} - -/* - * C: __~_ - * D: =~H~ - */ -static inline int iic_is_acknowledged(void) -{ - unsigned int dat, ack_bit; - - IIC_INIT(); - - IIC_SET_DAT - IIC_DELAY - IIC_SET_CLK - IIC_DELAY - - ack_bit = IIC_READ_DATA(); - - IIC_CLR_CLK - IIC_DELAY - - return ack_bit == 0; -} - -/* - * C: _~__~__~__~__~__~__~__~_ - * D: =DDXDDXDDXDDXDDXDDXDDXDD - */ -static void iic_sendbyte(unsigned int b) -{ - unsigned int dat, i; - - IIC_INIT(); - - for (i = 0; i < 8; i++) { - if (b & 128) - IIC_SET_DAT - else - IIC_CLR_DAT - IIC_DELAY - - IIC_SET_CLK - IIC_DELAY - IIC_CLR_CLK - IIC_DELAY - - b <<= 1; - } -} - -/* - * C: __~_~_~_~_~_~_~_~_ - * D: =~HHHHHHHHHHHHHHHH - */ -static unsigned char iic_recvbyte(void) -{ - unsigned int dat, i, in; - - IIC_INIT(); - - IIC_SET_DAT - IIC_DELAY - - in = 0; - for (i = 0; i < 8; i++) { - IIC_SET_CLK - IIC_DELAY - - in = (in << 1) | IIC_READ_DATA(); - - IIC_CLR_CLK - IIC_DELAY - } - - return in; -} - -int iic_control (unsigned char addr, unsigned char loc, unsigned char *buf, int len) -{ - int i, err = -EIO; - - iic_start(); - iic_sendbyte(addr & 0xfe); - if (!iic_is_acknowledged()) - goto error; - - iic_sendbyte(loc); - if (!iic_is_acknowledged()) - goto error; - - if (addr & 1) { - iic_stop(); - iic_start(); - iic_sendbyte(addr|1); - if (!iic_is_acknowledged()) - goto error; - - for (i = 0; i < len - 1; i++) { - buf[i] = iic_recvbyte(); - iic_acknowledge(); - } - buf[i] = iic_recvbyte(); - } else { - for (i = 0; i < len; i++) { - iic_sendbyte(buf[i]); - - if (!iic_is_acknowledged()) - goto error; - } - } - - err = 0; -error: - iic_stop(); - - return err; -} diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c --- v2.3.99-pre8/linux/arch/arm/kernel/traps.c Thu Feb 10 17:11:03 2000 +++ linux/arch/arm/kernel/traps.c Mon May 15 16:41:29 2000 @@ -399,13 +399,13 @@ printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line); if (data) printk(KERN_CRIT"extra data = %p\n", data); - *(int *)0 = 0; + BUG(); } void __readwrite_bug(const char *fn) { printk("%s called, but not implemented", fn); - *(int *)0 = 0; + BUG(); } void __pte_error(const char *file, int line, unsigned long val) @@ -436,7 +436,7 @@ printk(KERN_CRIT "abort() called from %p! (Please " "report to rmk@arm.linux.org.uk)\n", lr); - *(int *)0 = 0; + BUG(); /* if that doesn't kill us, halt */ panic("Oops failed to kill thread"); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile --- v2.3.99-pre8/linux/arch/arm/lib/Makefile Tue Apr 11 15:09:12 2000 +++ linux/arch/arm/lib/Makefile Mon May 15 12:00:33 2000 @@ -20,6 +20,7 @@ L_OBJS_clps7500 := io-acorn.o L_OBJS_ebsa110 := io-ebsa110.o L_OBJS_footbridge := io-footbridge.o +L_OBJS_l7200 := io-acorn.o L_OBJS_nexuspci := io-footbridge.o L_OBJS_sa1100 := io-footbridge.o L_OBJS_shark := io-shark.o diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.3.99-pre8/linux/arch/i386/config.in Thu May 11 15:30:05 2000 +++ linux/arch/i386/config.in Tue May 23 08:22:22 2000 @@ -180,7 +180,6 @@ bool ' Enable PM at boot time' CONFIG_APM_DO_ENABLE bool ' Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE bool ' Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK - 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 diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.3.99-pre8/linux/arch/i386/defconfig Fri May 12 14:18:55 2000 +++ linux/arch/i386/defconfig Mon May 15 13:11:34 2000 @@ -111,7 +111,6 @@ # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_RAID0 is not set -# CONFIG_RAID15_DANGEROUS is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set @@ -169,6 +168,13 @@ # CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set # CONFIG_BLK_DEV_IDECS is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/acpi.c linux/arch/i386/kernel/acpi.c --- v2.3.99-pre8/linux/arch/i386/kernel/acpi.c Thu May 11 15:30:06 2000 +++ linux/arch/i386/kernel/acpi.c Mon May 15 12:14:19 2000 @@ -829,7 +829,7 @@ {0x8086, 0x7113, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_INTEL_PIIX4}, {0x1106, 0x3040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VIA_586}, {0x1106, 0x3057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VIA_686A}, - {0,}, /* terminate list */ + {0,} /* terminate list */ }; static int __init acpi_probe(struct pci_dev *dev, diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c --- v2.3.99-pre8/linux/arch/i386/kernel/apic.c Thu May 11 15:30:06 2000 +++ linux/arch/i386/kernel/apic.c Sat May 13 07:37:34 2000 @@ -30,11 +30,6 @@ int prof_old_multiplier[NR_CPUS] = { 1, }; int prof_counter[NR_CPUS] = { 1, }; -/* - * IA s/w dev Vol 3, Section 7.4 - */ -#define APIC_DEFAULT_PHYS_BASE 0xfee00000 - int get_maxlvt(void) { unsigned int v, ver, maxlvt; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c --- v2.3.99-pre8/linux/arch/i386/kernel/apm.c Fri Mar 10 16:40:39 2000 +++ linux/arch/i386/kernel/apm.c Tue May 23 08:22:22 2000 @@ -132,6 +132,9 @@ * 1.13: Changes for new pm_ interfaces (Andy Henroid * ). * Modularize the code. + * Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS + * is now the way life works). + * Fix thinko in suspend() (wrong return). * * APM 1.1 Reference: * @@ -308,9 +311,7 @@ #endif static int suspends_pending = 0; static int standbys_pending = 0; -#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND static int waiting_for_resume = 0; -#endif #ifdef CONFIG_APM_RTC_IS_GMT # define clock_cmos_diff 0 @@ -866,22 +867,22 @@ static int suspend(void) { int err; - int ret; struct apm_user *as; get_time_diff(); err = apm_set_power_state(APM_STATE_SUSPEND); reinit_timer(); set_time(); - ret = (err == APM_SUCCESS) || (err == APM_NO_ERROR); - if (!ret) + if (err == APM_NO_ERROR) + err = APM_SUCCESS; + if (err != APM_SUCCESS) apm_error("suspend", err); for (as = user_list; as != NULL; as = as->next) { as->suspend_wait = 0; - as->suspend_result = (ret ? 0 : -EIO); + as->suspend_result = ((err == APM_SUCCESS) ? 0 : -EIO); } wake_up_interruptible(&apm_suspend_waitqueue); - return ret; + return err; } static void standby(void) @@ -962,14 +963,7 @@ switch (event) { case APM_SYS_STANDBY: case APM_USER_STANDBY: -#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND - if (waiting_for_resume) - break; -#endif if (send_event(event, NULL)) { -#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND - waiting_for_resume = 1; -#endif if (standbys_pending <= 0) standby(); } @@ -986,14 +980,18 @@ if (ignore_bounce) break; #endif -#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND + /* + * If we are already processing a SUSPEND, + * then further SUSPEND events from the BIOS + * will be ignored. We also return here to + * cope with the fact that the Thinkpads keep + * sending a SUSPEND event until something else + * happens! + */ if (waiting_for_resume) - break; -#endif + return; if (send_event(event, NULL)) { -#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND waiting_for_resume = 1; -#endif if (suspends_pending <= 0) (void) suspend(); } @@ -1002,9 +1000,7 @@ case APM_NORMAL_RESUME: case APM_CRITICAL_RESUME: case APM_STANDBY_RESUME: -#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND waiting_for_resume = 0; -#endif #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE last_resume = jiffies; ignore_bounce = 1; @@ -1036,8 +1032,10 @@ int err; if ((standbys_pending > 0) || (suspends_pending > 0)) { - if ((apm_bios_info.version > 0x100) && (pending_count-- < 0)) { + if ((apm_bios_info.version > 0x100) && (pending_count-- <= 0)) { pending_count = 4; + if (debug) + printk(KERN_DEBUG "apm: setting state busy\n"); err = apm_set_power_state(APM_STATE_BUSY); if (err) apm_error("busy", err); @@ -1097,7 +1095,7 @@ static int check_apm_user(struct apm_user *as, const char *func) { if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) { - printk(KERN_ERR "apm: %s passed bad filp", func); + printk(KERN_ERR "apm: %s passed bad filp\n", func); return 1; } return 0; @@ -1200,7 +1198,7 @@ } else if (!send_event(APM_USER_SUSPEND, as)) return -EAGAIN; if (suspends_pending <= 0) { - if (!suspend()) + if (suspend() != APM_SUCCESS) return -EIO; } else { as->suspend_wait = 1; @@ -1251,7 +1249,7 @@ as1 = as1->next) ; if (as1 == NULL) - printk(KERN_ERR "apm: filp not in user list"); + printk(KERN_ERR "apm: filp not in user list\n"); else as1->next = as->next; } @@ -1268,7 +1266,7 @@ as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL); if (as == NULL) { - printk(KERN_ERR "apm: cannot allocate struct of size %d bytes", + printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n", sizeof(*as)); MOD_DEC_USE_COUNT; return -ENOMEM; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/i8259.c linux/arch/i386/kernel/i8259.c --- v2.3.99-pre8/linux/arch/i386/kernel/i8259.c Wed Apr 26 16:34:06 2000 +++ linux/arch/i386/kernel/i8259.c Sat May 13 07:37:34 2000 @@ -456,7 +456,7 @@ * IRQ0 must be given a fixed assignment and initialized, * because it's used before the IO-APIC is set up. */ - set_intr_gate(IRQ0_TRAP_VECTOR, interrupt[0]); + set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]); /* * The reschedule interrupt is a CPU-to-CPU reschedule-helper diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c --- v2.3.99-pre8/linux/arch/i386/kernel/io_apic.c Wed Apr 26 16:34:06 2000 +++ linux/arch/i386/kernel/io_apic.c Sat May 13 07:37:34 2000 @@ -48,6 +48,11 @@ /* MP IRQ source entries */ int mp_irq_entries = 0; +#if CONFIG_SMP +# define TARGET_CPUS cpu_online_map +#else +# define TARGET_CPUS 0x01 +#endif /* * Rough estimation of how many shared IRQs there are, can * be changed anytime. @@ -89,7 +94,7 @@ entry->pin = pin; } -#define __DO_ACTION(name,R,ACTION, FINAL) \ +#define __DO_ACTION(R, ACTION, FINAL) \ \ { \ int pin; \ @@ -112,8 +117,8 @@ #define DO_ACTION(name,R,ACTION, FINAL) \ \ -static void name##_IO_APIC_irq(unsigned int irq) \ -__DO_ACTION(name,R,ACTION, FINAL) + static void name##_IO_APIC_irq (unsigned int irq) \ + __DO_ACTION(R, ACTION, FINAL) DO_ACTION( __mask, 0, |= 0x00010000, io_apic_sync(entry->apic))/* mask = 1 */ DO_ACTION( __unmask, 0, &= 0xfffeffff, ) /* mask = 0 */ @@ -542,25 +547,26 @@ return 0; } -int irq_vector[NR_IRQS] = { IRQ0_TRAP_VECTOR , 0 }; +int irq_vector[NR_IRQS] = { FIRST_DEVICE_VECTOR , 0 }; static int __init assign_irq_vector(int irq) { - static int current_vector = IRQ0_TRAP_VECTOR, offset = 0; + static int current_vector = FIRST_DEVICE_VECTOR, offset = 0; if (IO_APIC_VECTOR(irq) > 0) return IO_APIC_VECTOR(irq); - if (current_vector == 0xFF) - panic("ran out of interrupt sources!"); next: current_vector += 8; if (current_vector == SYSCALL_VECTOR) goto next; - if (current_vector > 0xFF) { + if (current_vector > FIRST_SYSTEM_VECTOR) { offset++; - current_vector = IRQ0_TRAP_VECTOR + offset; + current_vector = FIRST_DEVICE_VECTOR + offset; } + if (current_vector == FIRST_SYSTEM_VECTOR) + panic("ran out of interrupt sources!"); + IO_APIC_VECTOR(irq) = current_vector; return current_vector; } @@ -587,7 +593,7 @@ entry.delivery_mode = dest_LowestPrio; entry.dest_mode = 1; /* logical delivery */ entry.mask = 0; /* enable IRQ */ - entry.dest.logical.logical_dest = APIC_ALL_CPUS; + entry.dest.logical.logical_dest = TARGET_CPUS; idx = find_irq_entry(apic,pin,mp_INT); if (idx == -1) { @@ -605,7 +611,7 @@ if (irq_trigger(idx)) { entry.trigger = 1; entry.mask = 1; - entry.dest.logical.logical_dest = APIC_ALL_CPUS; + entry.dest.logical.logical_dest = TARGET_CPUS; } irq = pin_2_irq(idx, apic, pin); @@ -660,7 +666,7 @@ */ entry.dest_mode = 1; /* logical delivery */ entry.mask = 0; /* unmask IRQ now */ - entry.dest.logical.logical_dest = APIC_ALL_CPUS; + entry.dest.logical.logical_dest = TARGET_CPUS; entry.delivery_mode = dest_LowestPrio; entry.polarity = 0; entry.trigger = 0; @@ -1167,7 +1173,7 @@ mask = mask << 24; spin_lock_irqsave(&ioapic_lock, flags); - __DO_ACTION( target, 1, = mask, ) + __DO_ACTION(1, = mask, ) spin_unlock_irqrestore(&ioapic_lock, flags); } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.3.99-pre8/linux/arch/i386/kernel/irq.c Wed Apr 26 16:34:06 2000 +++ linux/arch/i386/kernel/irq.c Sat May 13 07:37:34 2000 @@ -1117,7 +1117,8 @@ struct proc_dir_entry *entry; char name [MAX_NAMELEN]; - if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type)) + if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) || + irq_dir[irq]) return; memset(name, 0, MAX_NAMELEN); @@ -1158,10 +1159,7 @@ /* * Create entries for all existing IRQs. */ - for (i = 0; i < NR_IRQS; i++) { - if (irq_desc[i].handler == &no_irq_type) - continue; + for (i = 0; i < NR_IRQS; i++) register_irq_proc(i); - } } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/ldt.c linux/arch/i386/kernel/ldt.c --- v2.3.99-pre8/linux/arch/i386/kernel/ldt.c Tue Aug 3 12:10:35 1999 +++ linux/arch/i386/kernel/ldt.c Sat May 20 10:39:58 2000 @@ -93,6 +93,7 @@ mm->segments = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE); if (!mm->segments) goto out_unlock; + memset(mm->segments, 0, LDT_ENTRIES*LDT_ENTRY_SIZE); if (atomic_read(&mm->mm_users) > 1) printk(KERN_WARNING "LDT allocated for cloned task!\n"); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/mpparse.c linux/arch/i386/kernel/mpparse.c --- v2.3.99-pre8/linux/arch/i386/kernel/mpparse.c Wed Apr 26 16:34:06 2000 +++ linux/arch/i386/kernel/mpparse.c Sat May 13 07:37:34 2000 @@ -50,11 +50,6 @@ unsigned long phys_cpu_present_map = 0; /* - * IA s/w dev Vol 3, Section 7.4 - */ -#define APIC_DEFAULT_PHYS_BASE 0xfee00000 - -/* * Intel MP BIOS table parsing routines: */ @@ -65,10 +60,12 @@ static int __init mpf_checksum(unsigned char *mp, int len) { - int sum=0; - while(len--) - sum+=*mp++; - return sum&0xFF; + int sum = 0; + + while (len--) + sum += *mp++; + + return sum & 0xFF; } /* diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/pci-i386.c linux/arch/i386/kernel/pci-i386.c --- v2.3.99-pre8/linux/arch/i386/kernel/pci-i386.c Thu May 11 15:30:06 2000 +++ linux/arch/i386/kernel/pci-i386.c Mon May 15 13:40:09 2000 @@ -121,6 +121,19 @@ } } +/* + * We need to avoid collisions with `mirrored' VGA ports + * and other strange ISA hardware, so we always want the + * addresses to be allocated in the 0x000-0x0ff region + * modulo 0x400. + * + * Why? Because some silly external IO cards only decode + * the low 10 bits of the IO address. The 0x00-0xff region + * is reserved for motherboard devices that decode all 16 + * bits, so it's ok to allocate at, say, 0x2800-0x28ff, + * but we want to try to avoid allocating at 0x2900-0x2bff + * which might have be mirrored at 0x0100-0x03ff.. + */ void pcibios_align_resource(void *data, struct resource *res, unsigned long size) { @@ -129,17 +142,16 @@ if (res->flags & IORESOURCE_IO) { unsigned long start = res->start; - /* We need to avoid collisions with `mirrored' VGA ports - and other strange ISA hardware, so we always want the - addresses kilobyte aligned. */ if (size > 0x100) { printk(KERN_ERR "PCI: I/O Region %s/%d too large" " (%ld bytes)\n", dev->slot_name, dev->resource - res, size); } - start = (start + 1024 - 1) & ~(1024 - 1); - res->start = start; + if (start & 0x300) { + start = (start + 0x3ff) & ~0x3ff; + res->start = start; + } } } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/pci-irq.c linux/arch/i386/kernel/pci-irq.c --- v2.3.99-pre8/linux/arch/i386/kernel/pci-irq.c Thu May 11 15:30:06 2000 +++ linux/arch/i386/kernel/pci-irq.c Sat May 13 07:34:49 2000 @@ -222,6 +222,7 @@ { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, pirq_piix_get, pirq_piix_set }, { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, pirq_piix_get, pirq_piix_set }, { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set }, + { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82440MX_1, pirq_piix_get, pirq_piix_set }, { "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set }, { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set }, { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, pirq_via_get, pirq_via_set }, @@ -345,7 +346,7 @@ if (!irq) { DBG(" ... failed\n"); - if (newirq && mask == (1 << newirq)) { + if (assign && newirq && mask == (1 << newirq)) { msg = "Guessed"; irq = newirq; } else diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c --- v2.3.99-pre8/linux/arch/i386/kernel/pci-pc.c Thu May 11 15:30:06 2000 +++ linux/arch/i386/kernel/pci-pc.c Sat May 20 11:32:08 2000 @@ -844,15 +844,15 @@ pcibios_last_bus = -1; } -static void __init pci_fixup_rcc(struct pci_dev *d) +static void __init pci_fixup_serverworks(struct pci_dev *d) { /* - * RCC host bridges -- Find and scan all secondary buses. + * ServerWorks host bridges -- Find and scan all secondary buses. * Register 0x44 contains first, 0x45 last bus number routed there. */ u8 busno; pci_read_config_byte(d, 0x44, &busno); - printk("PCI: RCC host bridge: secondary bus %02x\n", busno); + printk("PCI: ServerWorks host bridge: secondary bus %02x\n", busno); pci_scan_bus(busno, pci_root_ops, NULL); pcibios_last_bus = -1; } @@ -928,8 +928,9 @@ struct pci_fixup pcibios_fixups[] = { { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_RCC, PCI_DEVICE_ID_RCC_HE, pci_fixup_rcc }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_RCC, PCI_DEVICE_ID_RCC_LE, pci_fixup_rcc }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HE, pci_fixup_serverworks }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE, pci_fixup_serverworks }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CMIC_HE, pci_fixup_serverworks }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_6010, pci_fixup_compaq }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash }, diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.3.99-pre8/linux/arch/i386/kernel/setup.c Thu May 11 15:30:06 2000 +++ linux/arch/i386/kernel/setup.c Sat May 20 09:22:58 2000 @@ -406,6 +406,32 @@ e820.nr_map++; } /* add_memory_region */ +#define E820_DEBUG 1 + +static void __init print_e820_map(void) +{ + int i; + + for (i = 0; i < e820.nr_map; i++) { + printk(" e820: %016Lx @ %016Lx ", + e820.map[i].size, e820.map[i].addr); + switch (e820.map[i].type) { + case E820_RAM: printk("(usable)\n"); + break; + case E820_RESERVED: + printk("(reserved)\n"); + break; + case E820_ACPI: + printk("(ACPI data)\n"); + break; + case E820_NVS: + printk("(ACPI NVS)\n"); + break; + default: printk("type %lu\n", e820.map[i].type); + break; + } + } +} /* * Do NOT EVER look at the BIOS memory size location. @@ -415,11 +441,6 @@ void __init setup_memory_region(void) { -#define E820_DEBUG 1 -#ifdef E820_DEBUG - int i; -#endif - /* * If we're lucky and live on a modern system, the setup code * will have given us a memory map that we can use to properly @@ -439,27 +460,6 @@ if (e820.nr_map > E820MAX) e820.nr_map = E820MAX; memcpy(e820.map, E820_MAP, e820.nr_map * sizeof e820.map[0]); -#ifdef E820_DEBUG - for (i=0; i < e820.nr_map; i++) { - printk("e820: %08x @ %08x ", (int)e820.map[i].size, - (int)e820.map[i].addr); - switch (e820.map[i].type) { - case E820_RAM: printk("(usable)\n"); - break; - case E820_RESERVED: - printk("(reserved)\n"); - break; - case E820_ACPI: - printk("(ACPI data)\n"); - break; - case E820_NVS: - printk("(ACPI NVS)\n"); - break; - default: printk("type %lu\n", e820.map[i].type); - break; - } - } -#endif } else { /* otherwise fake a memory map; one section from 0k->640k, @@ -472,6 +472,8 @@ add_memory_region(0, LOWMEMSIZE(), E820_RAM); add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM); } + printk("BIOS-provided physical RAM map:\n"); + print_e820_map(); } /* setup_memory_region */ @@ -538,6 +540,10 @@ } *to = '\0'; *cmdline_p = command_line; + if (usermem) { + printk("user-defined physical RAM map:\n"); + print_e820_map(); + } } void __init setup_arch(char **cmdline_p) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.3.99-pre8/linux/arch/i386/kernel/traps.c Wed Apr 26 16:34:06 2000 +++ linux/arch/i386/kernel/traps.c Sat May 13 07:37:34 2000 @@ -790,7 +790,7 @@ * On normal SMP PC this is used only with SMP, but we have to * use it and set it up here to start the Cobalt clock */ - set_fixmap(FIX_APIC_BASE, APIC_PHYS_BASE); + set_fixmap(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE); printk("Local APIC ID %lx\n", apic_read(APIC_ID)); printk("Local APIC Version %lx\n", apic_read(APIC_LVR)); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v2.3.99-pre8/linux/arch/i386/mm/init.c Tue Mar 7 14:32:25 2000 +++ linux/arch/i386/mm/init.c Sat May 13 07:40:53 2000 @@ -242,8 +242,18 @@ pte_t *pte; pgd = swapper_pg_dir + __pgd_offset(vaddr); + if (pgd_none(*pgd)) { + printk("PAE BUG #00!\n"); + return; + } pmd = pmd_offset(pgd, vaddr); + if (pmd_none(*pmd)) { + printk("PAE BUG #01!\n"); + return; + } pte = pte_offset(pmd, vaddr); + if (pte_val(*pte)) + pte_ERROR(*pte); pgprot_val(prot) = pgprot_val(PAGE_KERNEL) | pgprot_val(flags); set_pte(pte, mk_pte_phys(phys, prot)); @@ -271,53 +281,65 @@ pmd_t *pmd; pte_t *pte; int i, j; + unsigned long vaddr; - i = __pgd_offset(start); - j = __pmd_offset(start); + vaddr = start; + i = __pgd_offset(vaddr); + j = __pmd_offset(vaddr); pgd = pgd_base + i; - for ( ; (i < PTRS_PER_PGD) && (start != end); pgd++, i++) { + for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) { #if CONFIG_X86_PAE if (pgd_none(*pgd)) { pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); set_pgd(pgd, __pgd(__pa(pmd) + 0x1)); - if (pmd != pmd_offset(pgd, start)) - BUG(); + if (pmd != pmd_offset(pgd, 0)) + printk("PAE BUG #02!\n"); } - pmd = pmd_offset(pgd, start); + pmd = pmd_offset(pgd, vaddr); #else pmd = (pmd_t *)pgd; #endif - for (; (j < PTRS_PER_PMD) && start; pmd++, j++) { + for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { if (pmd_none(*pmd)) { pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte))); if (pte != pte_offset(pmd, 0)) BUG(); } - start += PMD_SIZE; + vaddr += PMD_SIZE; } j = 0; } } -static void __init pagetable_init(void) +static void __init pagetable_init (void) { + unsigned long vaddr, end; pgd_t *pgd, *pgd_base; + int i, j, k; pmd_t *pmd; pte_t *pte; - int i, j, k; - unsigned long vaddr, end; - end = (unsigned long)__va(max_low_pfn*PAGE_SIZE) - 1; + /* + * This can be zero as well - no problem, in that case we exit + * the loops anyway due to the PTRS_PER_* conditions. + */ + end = (unsigned long)__va(max_low_pfn*PAGE_SIZE); - i = __pgd_offset(PAGE_OFFSET); pgd_base = swapper_pg_dir; +#if CONFIG_X86_PAE + for (i = 0; i < PTRS_PER_PGD; i++) { + pgd = pgd_base + i; + __pgd_clear(pgd); + } +#endif + i = __pgd_offset(PAGE_OFFSET); pgd = pgd_base + i; for (; i < PTRS_PER_PGD; pgd++, i++) { vaddr = i*PGDIR_SIZE; - if (vaddr >= end) + if (end && (vaddr >= end)) break; #if CONFIG_X86_PAE pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); @@ -329,7 +351,7 @@ BUG(); for (j = 0; j < PTRS_PER_PMD; pmd++, j++) { vaddr = i*PGDIR_SIZE + j*PMD_SIZE; - if (vaddr >= end) + if (end && (vaddr >= end)) break; if (cpu_has_pse) { unsigned long __pe; @@ -354,7 +376,7 @@ for (k = 0; k < PTRS_PER_PTE; pte++, k++) { vaddr = i*PGDIR_SIZE + j*PMD_SIZE + k*PAGE_SIZE; - if (vaddr >= end) + if (end && (vaddr >= end)) break; *pte = mk_pte_phys(__pa(vaddr), PAGE_KERNEL); } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ia64/ia32/sys_ia32.c linux/arch/ia64/ia32/sys_ia32.c --- v2.3.99-pre8/linux/arch/ia64/ia32/sys_ia32.c Wed Apr 26 16:34:06 2000 +++ linux/arch/ia64/ia32/sys_ia32.c Sat May 20 10:47:29 2000 @@ -2735,8 +2735,6 @@ extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type, unsigned long new_flags, void *data); -extern long do_sys_mount(char * dev_name, char * dir_name, char * type, - unsigned long new_flags, void *data); #define SMBFS_NAME "smbfs" #define NCPFS_NAME "ncpfs" @@ -2784,7 +2782,7 @@ do_smb_super_data_conv((void *)data_page); else panic("The problem is here..."); - err = do_sys_mount((char *)dev_page, (char *)dir_page, + err = do_mount((char *)dev_page, (char *)dir_page, (char *)type_page, new_flags, (void *)data_page); if(data_page) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/Makefile linux/arch/mips/Makefile --- v2.3.99-pre8/linux/arch/mips/Makefile Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/Makefile Sat May 13 08:29:14 2000 @@ -125,6 +125,7 @@ ifdef CONFIG_BAGET_MIPS SUBDIRS += arch/mips/baget arch/mips/baget/prom LIBS += arch/mips/baget/baget.a arch/mips/baget/prom/bagetlib.a +LOADADDR += 0x80001000 endif # @@ -189,6 +190,7 @@ @$(MAKEBOOT) clean $(MAKE) -C arch/$(ARCH)/kernel clean $(MAKE) -C arch/$(ARCH)/tools clean + $(MAKE) -C arch/mips/baget clean archmrproper: diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/Makefile linux/arch/mips/arc/Makefile --- v2.3.99-pre8/linux/arch/mips/arc/Makefile Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/arc/Makefile Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.2 2000/01/13 00:11:11 ralf Exp $ +# $Id: Makefile,v 1.1 1998/10/18 13:32:08 tsbogend Exp $ # # Makefile for the SGI arcs prom monitor library routines # under Linux. diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/cmdline.c linux/arch/mips/arc/cmdline.c --- v2.3.99-pre8/linux/arch/mips/arc/cmdline.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/arc/cmdline.c Sat May 13 08:29:14 2000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: cmdline.c,v 1.2 1999/10/09 00:00:57 ralf Exp $ + * $Id: cmdline.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/env.c linux/arch/mips/arc/env.c --- v2.3.99-pre8/linux/arch/mips/arc/env.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/arc/env.c Sat May 13 08:29:14 2000 @@ -11,12 +11,14 @@ #include -char * __init prom_getenv(char *name) +PCHAR __init +ArcGetEnvironmentVariable(CHAR *name) { return romvec->get_evar(name); } -long __init prom_setenv(char *name, char *value) +LONG __init +ArcSetEnvironmentVariable(PCHAR name, PCHAR value) { return romvec->set_evar(name, value); } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/file.c linux/arch/mips/arc/file.c --- v2.3.99-pre8/linux/arch/mips/arc/file.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/arc/file.c Sat May 13 08:29:14 2000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: file.c,v 1.2 1999/10/09 00:00:57 ralf Exp $ + * $Id: file.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/identify.c linux/arch/mips/arc/identify.c --- v2.3.99-pre8/linux/arch/mips/arc/identify.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/arc/identify.c Sat May 13 08:29:14 2000 @@ -7,7 +7,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: identify.c,v 1.3 1999/10/21 00:23:04 ralf Exp $ + * $Id: identify.c,v 1.2 1999/02/25 21:04:13 tsbogend Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/init.c linux/arch/mips/arc/init.c --- v2.3.99-pre8/linux/arch/mips/arc/init.c Thu Mar 2 14:36:22 2000 +++ linux/arch/mips/arc/init.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.4 1999/10/09 00:00:57 ralf Exp $ +/* $Id: init.c,v 1.5 2000/03/07 15:45:27 ralf Exp $ * This file is subject to the terms and conditions of the GNU General Public+ * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -23,7 +23,7 @@ extern void prom_testtree(void); -int __init prom_init(int argc, char **argv, char **envp) +int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) { struct linux_promblock *pb; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/memory.c linux/arch/mips/arc/memory.c --- v2.3.99-pre8/linux/arch/mips/arc/memory.c Thu Mar 2 14:36:22 2000 +++ linux/arch/mips/arc/memory.c Sat May 13 08:29:14 2000 @@ -21,8 +21,6 @@ #undef DEBUG -extern char _end; - struct linux_mdesc * __init ArcGetMemoryDescriptor(struct linux_mdesc *Current) { @@ -146,7 +144,7 @@ void __init prom_meminit(void) { struct prom_pmemblock *largest; - unsigned long bootmap_size; + unsigned long bootmap_size, kbegin, kend; struct linux_mdesc *p; int totram; int i = 0; @@ -195,6 +193,7 @@ pblocks[i].size = 0; max_low_pfn = find_max_low_pfn(); + largest = find_largest_memblock(); bootmap_size = init_bootmem(largest->base >> PAGE_SHIFT, max_low_pfn); @@ -208,6 +207,8 @@ prom_printf("CRITIAL: overwriting PROM data.\n"); BUG(); } + + /* Reserve the memory bootmap itself */ reserve_bootmem(largest->base, bootmap_size); printk("PROMLIB: Total free ram %dK / %dMB.\n", diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/misc.c linux/arch/mips/arc/misc.c --- v2.3.99-pre8/linux/arch/mips/arc/misc.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/arc/misc.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.2 1999/10/09 00:00:57 ralf Exp $ +/* $Id: misc.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $ * * misc.c: Miscellaneous ARCS PROM routines. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/salone.c linux/arch/mips/arc/salone.c --- v2.3.99-pre8/linux/arch/mips/arc/salone.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/arc/salone.c Sat May 13 08:29:14 2000 @@ -4,7 +4,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: salone.c,v 1.2 1999/10/09 00:00:57 ralf Exp $ + * $Id: salone.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/time.c linux/arch/mips/arc/time.c --- v2.3.99-pre8/linux/arch/mips/arc/time.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/arc/time.c Sat May 13 08:29:14 2000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: time.c,v 1.2 1999/10/09 00:00:57 ralf Exp $ + * $Id: time.c,v 1.1 1998/10/18 13:32:10 tsbogend Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/tree.c linux/arch/mips/arc/tree.c --- v2.3.99-pre8/linux/arch/mips/arc/tree.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/arc/tree.c Sat May 13 08:29:14 2000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: tree.c,v 1.2 1999/10/09 00:00:57 ralf Exp $ + * $Id: tree.c,v 1.1 1998/10/18 13:32:10 tsbogend Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/Makefile linux/arch/mips/baget/Makefile --- v2.3.99-pre8/linux/arch/mips/baget/Makefile Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/baget/Makefile Sat May 13 08:29:14 2000 @@ -11,11 +11,8 @@ all: baget.a -image: ../../../vmlinux - cp -f $< $@ - O_TARGET := baget.a -O_OBJS := baget.o print.o setup.o time.o irq.o bagetIRQ.o reset.o +O_OBJS := baget.o print.o setup.o time.o irq.o bagetIRQ.o reset.o wbflush.o ifeq ($(CONFIG_SERIAL),y) OX_OBJS += vacserial.o @@ -38,8 +35,8 @@ ##################### Baget Loader stuff ######################## -dummy.c: - touch $@ +image: ../../../vmlinux + cp -f $< $@ image.bin: image $(OBJCOPY) -O binary $< $@ @@ -47,6 +44,9 @@ ramdisk.bin: echo "Dummy ramdisk used. Provide your own if needed !" > $@ +dummy.c: + touch $@ + dummy.o: dummy.c image.bin ramdisk.bin $(CC) $(CFLAGS) -c -o $@ $< $(OBJCOPY) --add-section=.vmlinux=image.bin \ @@ -54,10 +54,11 @@ balo.h: image $(NM) $< | awk ' \ - BEGIN { printf "/* DO NOT EDIT THIS FILE */\n" } \ - /kernel_entry/ { printf "#define START 0x%s\n", $$1 } \ - /balo_ramdisk_base/ { printf "#define RAMDISK_BASE 0x%s\n", $$1 } \ - /balo_ramdisk_size/ { printf "#define RAMDISK_SIZE 0x%s\n", $$1 } \ + BEGIN { printf "/* DO NOT EDIT THIS FILE */\n" } \ + /_ftext/ { printf "#define LOADADDR 0x%s\n", $$1 } \ + /kernel_entry/ { printf "#define START 0x%s\n", $$1 } \ + /balo_ramdisk_base/ { printf "#define RAMDISK_BASE 0x%s\n", $$1 } \ + /balo_ramdisk_size/ { printf "#define RAMDISK_SIZE 0x%s\n", $$1 } \ ' > $@ balo.o: balo.c balo.h $(CC) $(CFLAGS) -c $< @@ -69,7 +70,6 @@ $(LD) $(LDFLAGS) -T ld.script.balo -o $@ $^ clean: - rm -f balo.o balo.h dummy.o dummy.c hello.o image.bin image balo_supp.o - rm -f $(O_OBJS) $(O_TARGET) + rm -f balo balo.h dummy.c image image.bin include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/baget.c linux/arch/mips/baget/baget.c --- v2.3.99-pre8/linux/arch/mips/baget/baget.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/baget/baget.c Sat May 13 08:29:14 2000 @@ -13,15 +13,9 @@ #include #include #include +#include #include - -/* - * Following values are set by BALO into RAM disk buffer parameters - */ -unsigned long balo_ramdisk_base = 0xBA; /* Signature for BALO ! */ -unsigned long balo_ramdisk_size = 0; - /* * Following code is based on routines from 'mm/vmalloc.c' diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/bagetIRQ.S linux/arch/mips/baget/bagetIRQ.S --- v2.3.99-pre8/linux/arch/mips/baget/bagetIRQ.S Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/baget/bagetIRQ.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: bagetIRQ.S,v 1.2 1999/08/18 23:37:42 ralf Exp $ +/* $Id: bagetIRQ.S,v 1.1 1999/01/17 03:49:37 ralf Exp $ * bagetIRQ.S: Interrupt exception dispatch code for Baget/MIPS * * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/balo.c linux/arch/mips/baget/balo.c --- v2.3.99-pre8/linux/arch/mips/baget/balo.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/baget/balo.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: balo.c,v 1.1 1999/01/17 03:49:37 ralf Exp $ +/* $Id$ * * balo.c: BAget LOader * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/irq.c linux/arch/mips/baget/irq.c --- v2.3.99-pre8/linux/arch/mips/baget/irq.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/baget/irq.c Sat May 13 08:29:14 2000 @@ -29,8 +29,7 @@ #include -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; +irq_cpustat_t irq_stat [NR_CPUS]; unsigned long spurious_count = 0; /* diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/print.c linux/arch/mips/baget/print.c --- v2.3.99-pre8/linux/arch/mips/baget/print.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/baget/print.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: print.c,v 1.2 1999/10/09 00:00:57 ralf Exp $ +/* $Id: print.c,v 1.1 1999/01/17 03:49:38 ralf Exp $ * * print.c: Simple print fascility * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/prom/Makefile linux/arch/mips/baget/prom/Makefile --- v2.3.99-pre8/linux/arch/mips/baget/prom/Makefile Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/baget/prom/Makefile Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.1 1999/01/17 03:49:40 ralf Exp $ +# $Id$ # Makefile for the Baget/MIPS prom emulator library routines. # # Note! Dependencies are done automagically by 'make dep', which also diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/time.c linux/arch/mips/baget/time.c --- v2.3.99-pre8/linux/arch/mips/baget/time.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/baget/time.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.4 1999/10/09 00:00:57 ralf Exp $ +/* $Id: time.c,v 1.3 1999/08/17 22:18:37 ralf Exp $ * time.c: Baget/MIPS specific time handling details * * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/vacserial.c linux/arch/mips/baget/vacserial.c --- v2.3.99-pre8/linux/arch/mips/baget/vacserial.c Wed Apr 26 16:34:06 2000 +++ linux/arch/mips/baget/vacserial.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: vacserial.c,v 1.4 1999/10/09 00:00:57 ralf Exp $ +/* $Id: vacserial.c,v 1.3 1999/08/17 22:18:37 ralf Exp $ * vacserial.c: VAC UART serial driver * This code stealed and adopted from linux/drivers/char/serial.c * See that for author info diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/boot/Makefile linux/arch/mips/boot/Makefile --- v2.3.99-pre8/linux/arch/mips/boot/Makefile Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/boot/Makefile Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.10 1999/10/17 19:55:22 harald Exp $ +# $Id: Makefile,v 1.9 1999/04/07 18:45:23 harald Exp $ # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/config.in linux/arch/mips/config.in --- v2.3.99-pre8/linux/arch/mips/config.in Tue Apr 11 15:09:13 2000 +++ linux/arch/mips/config.in Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.42 2000/02/24 00:12:40 ralf Exp $ +# $Id: config.in,v 1.46 2000/03/26 22:59:01 ralf Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -26,168 +26,169 @@ # # Select some configuration options automatically for certain systems. # +unset CONFIG_ARC32 +unset CONFIG_PCI +unset CONFIG_ISA unset CONFIG_MIPS_JAZZ unset CONFIG_VIDEO_G364 define_bool CONFIG_SBUS n -if [ "$CONFIG_ALGOR_P4032" = "y" -o "$CONFIG_SNI_RM200_PCI" = "y" -o \ - "$CONFIG_DDB5074" = "y" ]; then +if [ "$CONFIG_ALGOR_P4032" = "y" ]; then define_bool CONFIG_PCI y -else - define_bool CONFIG_PCI n fi -if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o "$CONFIG_OLIVETTI_M700" = "y" -o \ - "$CONFIG_SNI_RM200_PCI" = "y" -o "$CONFIG_ACER_PICA_61" = "y" ]; then - define_bool CONFIG_ISA y -else - define_bool CONFIG_ISA n -fi - if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \ "$CONFIG_OLIVETTI_M700" = "y" ]; then + define_bool CONFIG_ARC32 y define_bool CONFIG_HAVE_IO_PORTS y - define_bool CONFIG_MIPS_JAZZ y define_bool CONFIG_FB y define_bool CONFIG_FB_G364 y + define_bool CONFIG_MIPS_JAZZ y fi if [ "$CONFIG_ACER_PICA_61" = "y" ]; then + define_bool CONFIG_ARC32 y define_bool CONFIG_HAVE_IO_PORTS y define_bool CONFIG_MIPS_JAZZ y fi +if [ "$CONFIG_SGI_IP22" = "y" ]; then + define_bool CONFIG_ARC32 y +fi if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then + define_bool CONFIG_ARC32 y define_bool CONFIG_HAVE_IO_PORTS y fi if [ "$CONFIG_DDB5074" = "y" ]; then define_bool CONFIG_HAVE_IO_PORTS y + define_bool CONFIG_ISA y + define_bool CONFIG_PCI y +fi + +if [ "$CONFIG_ISA" != "y" ]; then + define_bool CONFIG_ISA n +fi + +if [ "$CONFIG_PCI" != "y" ]; then + define_bool CONFIG_PCI n fi endmenu mainmenu_option next_comment -comment 'CPU selection' - -if [ "$CONFIG_CPU_ADVANCED" = "y" ]; then - choice 'CPU core' \ - "R3000 CONFIG_CPU_R3000 \ - R4300 CONFIG_CPU_R4300 \ - R4x00 CONFIG_CPU_R4X00 \ - R5000 CONFIG_CPU_R5000 \ - R56x0 CONFIG_CPU_NEVADA \ - R10000 CONFIG_CPU_R10000" R4x00 + comment 'CPU selection' - bool ' ll/sc Instructions available' CONFIG_CPU_HAS_LLSC - bool ' Writeback Buffer available' CONFIG_CPU_HAS_WB -else - choice 'CPU type' \ - "R3000 CONFIG_CPU_R3000 \ - R6000 CONFIG_CPU_R6000 \ - R4300 CONFIG_CPU_R4300 \ - R4x00 CONFIG_CPU_R4X00 \ - R5000 CONFIG_CPU_R5000 \ - R56x0 CONFIG_CPU_NEVADA \ - R8000 CONFIG_CPU_R8000 \ - R10000 CONFIG_CPU_R10000 \ - Advanced CONFIG_CPU_ADVANCED" R4x00 - - if [ "$CONFIG_CPU_R3000" = "y" ]; then - if [ "$CONFIG_DECSTATION" = "y" ]; then - define_bool CONFIG_CPU_HAS_LLSC n - define_bool CONFIG_CPU_HAS_WB y - else - define_bool CONFIG_CPU_HAS_LLSC n - define_bool CONFIG_CPU_HAS_WB n - fi - else - define_bool CONFIG_CPU_HAS_LLSC y - define_bool CONFIG_CPU_HAS_WB n - fi -fi + choice 'CPU type' \ + "R3000 CONFIG_CPU_R3000 \ + R6000 CONFIG_CPU_R6000 \ + R4300 CONFIG_CPU_R4300 \ + R4x00 CONFIG_CPU_R4X00 \ + R5000 CONFIG_CPU_R5000 \ + R56x0 CONFIG_CPU_NEVADA \ + R8000 CONFIG_CPU_R8000 \ + R10000 CONFIG_CPU_R10000" R4x00 + + bool 'Advanced CPU Config' CONFIG_CPU_ADVANCED + + if [ "$CONFIG_CPU_ADVANCED" = "y" ]; then + bool ' ll/sc Instructions available' CONFIG_CPU_HAS_LLSC + bool ' Writeback Buffer available' CONFIG_CPU_HAS_WB + else + if [ "$CONFIG_CPU_R3000" = "y" ]; then + if [ "$CONFIG_DECSTATION" = "y" ]; then + define_bool CONFIG_CPU_HAS_LLSC n + define_bool CONFIG_CPU_HAS_WB y + else + define_bool CONFIG_CPU_HAS_LLSC n + define_bool CONFIG_CPU_HAS_WB n + fi + else + define_bool CONFIG_CPU_HAS_LLSC y + define_bool CONFIG_CPU_HAS_WB n + fi + fi endmenu mainmenu_option next_comment comment 'General setup' -if [ "$CONFIG_DECSTATION" = "y" -o "$CONFIG_DDB5074" = "y" ]; then - define_bool CONFIG_CPU_LITTLE_ENDIAN y -else - bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN -fi - -if [ "$CONFIG_PROC_FS" = "y" ]; then - define_bool CONFIG_KCORE_ELF y -fi -define_bool CONFIG_ELF_KERNEL y + if [ "$CONFIG_DECSTATION" = "y" -o "$CONFIG_DDB5074" = "y" ]; then + define_bool CONFIG_CPU_LITTLE_ENDIAN y + else + bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN + fi + + if [ "$CONFIG_PROC_FS" = "y" ]; then + define_bool CONFIG_KCORE_ELF y + fi + define_bool CONFIG_ELF_KERNEL y + + if [ "$CONFIG_CPU_LITTLE_ENDIAN" = "n" ]; then + bool 'Include IRIX binary compatibility' CONFIG_BINFMT_IRIX + bool 'Include forward keyboard' CONFIG_FORWARD_KEYBOARD + fi + + define_bool CONFIG_BINFMT_AOUT n + define_bool CONFIG_BINFMT_ELF y + tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC + + bool 'Networking support' CONFIG_NET + + if [ "$CONFIG_PCI" = "y" ]; then + source drivers/pci/Config.in + fi + + bool 'System V IPC' CONFIG_SYSVIPC + bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT + bool 'Sysctl support' CONFIG_SYSCTL + + source drivers/parport/Config.in + + bool 'Enable loadable module support' CONFIG_MODULES + if [ "$CONFIG_MODULES" = "y" ]; then + bool ' Set version information on all symbols for modules' CONFIG_MODVERSIONS + bool ' Kernel module loader' CONFIG_KMOD + fi + + if [ "$CONFIG_DECSTATION" = "y" ]; then + bool 'TURBOchannel support' CONFIG_TC + fi +endmenu -if [ "$CONFIG_CPU_LITTLE_ENDIAN" = "n" ]; then - define_bool CONFIG_BINFMT_IRIX y - define_bool CONFIG_FORWARD_KEYBOARD y +if [ "$CONFIG_ISA" = "y" ]; then + source drivers/pnp/Config.in fi -define_bool CONFIG_BINFMT_AOUT n -define_bool CONFIG_BINFMT_ELF y -tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC - -bool 'Networking support' CONFIG_NET -source drivers/pci/Config.in - -bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG -if [ "$CONFIG_HOTPLUG" = "y" ]; then +if [ "$CONFIG_HOTPLUG" = "y" ] ; then source drivers/pcmcia/Config.in else define_bool CONFIG_PCMCIA n fi -bool 'System V IPC' CONFIG_SYSVIPC -bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT -bool 'Sysctl support' CONFIG_SYSCTL - -if [ "$CONFIG_SGI_IP22" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then - source drivers/parport/Config.in -fi -endmenu - -mainmenu_option next_comment -comment 'Loadable module support' -bool 'Enable loadable module support' CONFIG_MODULES -if [ "$CONFIG_MODULES" = "y" ]; then - bool ' Set version information on all symbols for modules' CONFIG_MODVERSIONS - bool ' Kernel module loader' CONFIG_KMOD -fi - -source drivers/pci/Config.in - -endmenu - -if [ "$CONFIG_DECSTATION" = "y" ]; then - mainmenu_option next_comment - comment 'TURBOchannel support' - bool 'TURBOchannel support' CONFIG_TC -# if [ "$CONFIG_TC" = "y" ]; then -# tristate ' MAGMA Parallel port support' CONFIG_PARPORT -# fi - endmenu -fi - -source drivers/pnp/Config.in - source drivers/block/Config.in if [ "$CONFIG_NET" = "y" ]; then source net/Config.in fi -mainmenu_option next_comment -comment 'ATA/IDE/MFM/RLL support' - -tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE +if [ "$CONFIG_DECSTATION" != "n" -a \ + "$CONFIG_SGI_IP22" != "n" ]; then + source drivers/telephony/Config.in +fi -if [ "$CONFIG_IDE" != "n" ]; then - source drivers/ide/Config.in -else - define_bool CONFIG_BLK_DEV_IDE_MODES n - define_bool CONFIG_BLK_DEV_HD n +if [ "$CONFIG_SGI_IP22" != "n" -a \ + "$CONFIG_DECSTATION" != "n" ]; then + + mainmenu_option next_comment + comment 'ATA/IDE/MFM/RLL support' + + tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE + + if [ "$CONFIG_IDE" != "n" ]; then + source drivers/ide/Config.in + else + define_bool CONFIG_BLK_DEV_IDE_MODES n + define_bool CONFIG_BLK_DEV_HD n + fi + endmenu fi -endmenu mainmenu_option next_comment comment 'SCSI support' @@ -195,77 +196,57 @@ tristate 'SCSI support' CONFIG_SCSI if [ "$CONFIG_SCSI" != "n" ]; then - if [ "$CONFIG_SGI" = "y" -o "$CONFIG_DECSTATION" = "y" ]; then - comment ' SCSI support type (disk, tape, CDrom)' - - dep_tristate ' SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI - dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI - dep_tristate ' SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI - dep_tristate ' SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI - - comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs' - - bool ' Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN - - bool ' Verbose SCSI error reporting' CONFIG_SCSI_CONSTANTS - - #mainmenu_option next_comment - comment 'SCSI low-level drivers' - if [ "$CONFIG_SGI" = "y" ]; then - dep_tristate 'SGI wd93 Scsi Driver' CONFIG_SCSI_SGIWD93 $CONFIG_SCSI - else - if [ "$CONFIG_TC" = "y" ]; then - dep_tristate 'DEC NCR53C94 Scsi Driver' CONFIG_SCSI_DECNCR $CONFIG_SCSI - fi - dep_tristate 'DEC SII Scsi Driver' CONFIG_SCSI_DECSII $CONFIG_SCSI - fi - else - source drivers/scsi/Config.in - fi + source drivers/scsi/Config.in fi endmenu +if [ "$CONFIG_DECSTATION" != "n" -a \ + "$CONFIG_SGI_IP22" != "n" ]; then + source drivers/i2o/Config.in +fi + if [ "$CONFIG_NET" = "y" ]; then mainmenu_option next_comment comment 'Network device support' bool 'Network device support' CONFIG_NETDEVICES if [ "$CONFIG_NETDEVICES" = "y" ]; then - if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then + + if [ "$CONFIG_SGI_IP22" != "y" -a \ + "$CONFIG_DECSTATION" != "y" -a \ + "$CONFIG_BAGET_MIPS" != "y" ]; then + source drivers/net/Config.in + + if [ "$CONFIG_ATM" = "y" ]; then + source drivers/atm/Config.in + fi else - tristate ' Dummy net driver support' CONFIG_DUMMY - tristate ' SLIP (serial line) support' CONFIG_SLIP + tristate 'Dummy net driver support' CONFIG_DUMMY + tristate 'SLIP (serial line) support' CONFIG_SLIP if [ "$CONFIG_SLIP" != "n" ]; then - bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED - bool ' Keepalive and linefill' CONFIG_SLIP_SMART + bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED + bool ' Keepalive and linefill' CONFIG_SLIP_SMART fi - tristate ' PPP (point-to-point) support' CONFIG_PPP + tristate 'PPP (point-to-point) support' CONFIG_PPP if [ ! "$CONFIG_PPP" = "n" ]; then - comment ' CCP compressors for PPP are only built as modules.' + comment 'CCP compressors for PPP are only built as modules.' + fi + if [ "$CONFIG_SGI_IP22" = "y" ]; then + bool 'SGI Seeq ethernet controller support' CONFIG_SGISEEQ + fi + if [ "$CONFIG_DECSTATION" = "y" ]; then + bool 'DEC LANCE ethernet controller support' CONFIG_DECLANCE + fi + if [ "$CONFIG_BAGET_MIPS" = "y" ]; then + tristate 'Baget AMD LANCE support' CONFIG_BAGETLANCE fi - if [ "$CONFIG_SGI" = "y" ]; then - bool ' SGI Seeq ethernet controller support' CONFIG_SGISEEQ - fi - fi - if [ "$CONFIG_DECSTATION" = "y" ]; then - bool ' DEC LANCE ethernet controller support' CONFIG_DECLANCE - fi - if [ "$CONFIG_BAGET_MIPS" = "y" ]; then - tristate ' Baget AMD LANCE support' CONFIG_BAGETLANCE - tristate ' Baget Backplane Shared Memory support' CONFIG_BAGETBSM fi fi endmenu fi -if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then - mainmenu_option next_comment - # comment 'AX.25 network device drivers' - - source drivers/net/hamradio/Config.in - endmenu - +if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" ]; then mainmenu_option next_comment comment 'ISDN subsystem' @@ -287,20 +268,20 @@ endmenu fi -if [ "$CONFIG_DECSTATION" != "y" ]; then +if [ "$CONFIG_DECSTATION" != "n" -a \ + "$CONFIG_SGI_IP22" != "n" ]; then source drivers/char/Config.in -else +fi + +if [ "$CONFIG_DECSTATION" = "y" ]; then mainmenu_option next_comment - comment 'DECstation Character devices' + comment 'DECStation Character devices' bool 'Virtual terminal' CONFIG_VT if [ "$CONFIG_VT" = "y" ]; then bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE fi tristate 'Standard/generic (dumb) serial support' CONFIG_SERIAL - if [ "$CONFIG_SGI_IP22" = "y" ]; then - bool 'SGI PROM Console Support' CONFIG_SGI_PROM_CONSOLE - fi if [ "$CONFIG_SERIAL" = "y" ]; then bool 'DZ11 Serial Support' CONFIG_DZ if [ "$CONFIG_TC" = "y" ]; then @@ -314,32 +295,42 @@ fi bool 'Keyboard Support' CONFIG_KEYBOARD bool 'Mouse Support' CONFIG_MOUSE -# bool 'Enhanced Real Time Clock Support' CONFIG_RTC + bool 'Enhanced Real Time Clock Support' CONFIG_RTC endmenu fi - -#source drivers/misc/Config.in - -source fs/Config.in - -if [ "$CONFIG_VT" = "y" ]; then +if [ "$CONFIG_SGI_IP22" = "y" ]; then mainmenu_option next_comment - comment 'Console drivers' - if [ "$CONFIG_SGI_IP22" = "y" ]; then + comment 'SGI Character devices' + bool 'Virtual terminal' CONFIG_VT + if [ "$CONFIG_VT" = "y" ]; then + bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE tristate 'SGI Newport Console support' CONFIG_SGI_NEWPORT_CONSOLE if [ "$CONFIG_SGI_NEWPORT_CONSOLE" != "y" ]; then define_bool CONFIG_DUMMY_CONSOLE y else define_bool CONFIG_FONT_8x16 y fi - else + bool 'SGI PROM Console Support' CONFIG_SGI_PROM_CONSOLE + fi + bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS + if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then + int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 + fi + endmenu +fi + +source fs/Config.in + +if [ "$CONFIG_VT" = "y" ]; then + mainmenu_option next_comment + + comment 'Console drivers' if [ "$CONFIG_DECSTATION" != "y" ]; then bool 'VGA text console' CONFIG_VGA_CONSOLE fi - bool 'Support for frame buffer devices' CONFIG_FB - source drivers/video/Config.in - fi + bool 'Support for frame buffer devices' CONFIG_FB + source drivers/video/Config.in endmenu fi @@ -363,7 +354,6 @@ mainmenu_option next_comment comment 'Kernel hacking' -#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC bool 'Are you using a crosscompiler' CONFIG_CROSSCOMPILE if [ "$CONFIG_MODULES" = "y" ]; then bool ' Build fp execption handler module' CONFIG_MIPS_FPE_MODULE diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/Makefile linux/arch/mips/ddb5074/Makefile --- v2.3.99-pre8/linux/arch/mips/ddb5074/Makefile Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/ddb5074/Makefile Sat May 13 08:29:14 2000 @@ -8,7 +8,7 @@ # # Note 2! The CFLAGS definitions are now in the main makefile... # -# $Id: Makefile,v 1.1 2000/01/26 00:07:44 ralf Exp $ +# $Id$ # .S.s: @@ -17,6 +17,6 @@ $(CC) $(CFLAGS) -c $< -o $*.o O_TARGET = ddb5074.a -O_OBJS = setup.o irq.o time.o prom.o pci.o int-handler.o nile4.o +O_OBJS = setup.o irq.o time.o prom.o pci.o pci-dma.o int-handler.o nile4.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/int-handler.S linux/arch/mips/ddb5074/int-handler.S --- v2.3.99-pre8/linux/arch/mips/ddb5074/int-handler.S Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/ddb5074/int-handler.S Sat May 13 08:29:14 2000 @@ -6,9 +6,9 @@ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * * Copyright (C) 2000 Geert Uytterhoeven - * Sony Suprastructure Center Europe (SUPC-E), Brussels + * Sony Software Development Center Europe (SDCE), Brussels * - * $Id: int-handler.S,v 1.2 2000/01/27 02:06:56 ralf Exp $ + * $Id: int-handler.S,v 1.1 2000/01/26 00:07:44 ralf Exp $ */ #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/irq.c linux/arch/mips/ddb5074/irq.c --- v2.3.99-pre8/linux/arch/mips/ddb5074/irq.c Thu Mar 2 14:36:22 2000 +++ linux/arch/mips/ddb5074/irq.c Sat May 13 08:29:14 2000 @@ -2,7 +2,7 @@ * arch/mips/ddb5074/irq.c -- NEC DDB Vrc-5074 interrupt routines * * Copyright (C) 2000 Geert Uytterhoeven - * Sony Suprastructure Center Europe (SUPC-E), Brussels + * Sony Software Development Center Europe (SDCE), Brussels * * $Id: irq.c,v 1.1 2000/01/26 00:07:44 ralf Exp $ */ @@ -30,7 +30,7 @@ extern asmlinkage void do_IRQ(int irq, struct pt_regs * regs); -static void no_action(int cpl, void *dev_id, struct pt_regs *regs) +void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/nile4.c linux/arch/mips/ddb5074/nile4.c --- v2.3.99-pre8/linux/arch/mips/ddb5074/nile4.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/ddb5074/nile4.c Sat May 13 08:29:14 2000 @@ -2,9 +2,9 @@ * arch/mips/ddb5074/nile4.c -- NEC Vrc-5074 Nile 4 support routines * * Copyright (C) 2000 Geert Uytterhoeven - * Sony Suprastructure Center Europe (SUPC-E), Brussels + * Sony Software Development Center Europe (SDCE), Brussels * - * $Id: nile4.c,v 1.1 2000/01/26 00:07:44 ralf Exp $ + * $Id$ */ #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/pci-dma.c linux/arch/mips/ddb5074/pci-dma.c --- v2.3.99-pre8/linux/arch/mips/ddb5074/pci-dma.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips/ddb5074/pci-dma.c Sat May 13 08:29:14 2000 @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2000 Ani Joshi + * + * + * Dynamic DMA mapping support. + * + * swiped from i386, and cloned for MIPS by Geert. + * + */ + +#include +#include +#include +#include +#include + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t *dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC; + + if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) + gfp |= GFP_DMA; + ret = (void *)__get_free_pages(gfp, get_order(size)); + + if (ret != NULL) { + memset(ret, 0, size); + *dma_handle = virt_to_bus(ret); + } + return ret; +} + +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + free_pages((unsigned long)vaddr, get_order(size)); +} diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/pci.c linux/arch/mips/ddb5074/pci.c --- v2.3.99-pre8/linux/arch/mips/ddb5074/pci.c Thu Mar 2 14:36:22 2000 +++ linux/arch/mips/ddb5074/pci.c Sat May 13 08:29:14 2000 @@ -3,7 +3,7 @@ * * Copyright (C) 2000 Geert Uytterhoeven * Albert Dorofeev - * Sony Suprastructure Center Europe (SUPC-E), Brussels + * Sony Software Development Center Europe (SDCE), Brussels * * $Id: pci.c,v 1.4 2000/02/18 00:02:17 ralf Exp $ */ @@ -168,163 +168,136 @@ nile4_pci_write_config_dword }; +struct { + struct resource ram; + struct resource flash; + struct resource isa_io; + struct resource pci_io; + struct resource isa_mem; + struct resource pci_mem; + struct resource nile4; + struct resource boot; +} ddb5074_resources = { + { "RAM", 0x00000000, 0x03ffffff, + IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 }, + { "Flash ROM", 0x04000000, 0x043fffff }, + { "Nile4 ISA I/O", 0x06000000, 0x060fffff }, + { "Nile4 PCI I/O", 0x06100000, 0x07ffffff }, + { "Nile4 ISA mem", 0x08000000, 0x08ffffff, IORESOURCE_MEM }, + { "Nile4 PCI mem", 0x09000000, 0x0fffffff, IORESOURCE_MEM }, + { "Nile4 ctrl", 0x1fa00000, 0x1fbfffff, + IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 }, + { "Boot ROM", 0x1fc00000, 0x1fffffff } +}; -static void __init pcibios_claim_resources(struct list_head *bus_list) +static void __init ddb5074_pci_fixup(void) { - struct list_head *ln, *dn; - struct pci_bus *bus; struct pci_dev *dev; - int idx; - for (ln = bus_list->next; ln != bus_list; ln = ln->next) { - bus = pci_bus_b(ln); - for (dn = bus->devices.next; dn != &bus->devices; dn = dn->next) { - dev = pci_dev_b(dn); - for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) { - struct resource *r = &dev->resource[idx]; - struct resource *pr; - if (!r->start) - continue; - pr = pci_find_parent_resource(dev, r); - if (!pr || request_resource(pr, r) < 0) { - printk(KERN_ERR "PCI: Address space collision on region %d of device %s\n", idx, dev->name); - /* We probably should disable the region, shouldn't we? */ - } - } + pci_for_each_dev(dev) { + if (dev->vendor == PCI_VENDOR_ID_NEC && + dev->device == PCI_DEVICE_ID_NEC_NILE4) { + /* + * The first 64-bit PCI base register should point to the Nile4 + * control registers. Unfortunately this isn't the case, so we fix + * it ourselves. This allows the serial driver to find the UART. + */ + dev->resource[0] = ddb5074_resources.nile4; + request_resource(&iomem_resource, &dev->resource[0]); + /* + * The second 64-bit PCI base register points to the first memory + * bank. Unfortunately the address is wrong, so we fix it (again). + */ + dev->resource[2] = ddb5074_resources.ram; + request_resource(&iomem_resource, &dev->resource[2]); + } else if (dev->vendor == PCI_VENDOR_ID_AL && + dev->device == PCI_DEVICE_ID_AL_M7101) { + /* + * It's nice to have the LEDs on the GPIO pins available for + * debugging + */ + extern struct pci_dev *pci_pmu; + u8 t8; + + pci_pmu = dev; /* for LEDs D2 and D3 */ + /* Program the lines for LEDs D2 and D3 to output */ + nile4_pci_read_config_byte(dev, 0x7d, &t8); + t8 |= 0xc0; + nile4_pci_write_config_byte(dev, 0x7d, t8); + /* Turn LEDs D2 and D3 off */ + nile4_pci_read_config_byte(dev, 0x7e, &t8); + t8 |= 0xc0; + nile4_pci_write_config_byte(dev, 0x7e, t8); } - pcibios_claim_resources(&bus->children); } } - -void pcibios_init(void) +static void __init pcibios_fixup_irqs(void) { - printk("PCI: Probing PCI hardware\n"); - ioport_resource.end = 0x1ffffff; - pci_scan_bus(0, &nile4_pci_ops, NULL); - pcibios_claim_resources(&pci_root_buses); -} - -void pcibios_fixup_bus(struct pci_bus *bus) -{ - struct list_head *dn; struct pci_dev *dev; - extern struct pci_dev *pci_pmu; /* for LEDs D2 and D3 */ - int slot_num, func_num; - u8 t8; - - /* - * FIXME: PMON doesn't autoconfigure the PCI devices - * For now we just hardcode them for our configuration - */ - printk("PCI: Configuring PCI devices (hardcoded)\n"); - for (dn = bus->devices.next; dn != &bus->devices; dn = dn->next) { - dev = pci_dev_b(dn); + int slot_num; + pci_for_each_dev(dev) { slot_num = PCI_SLOT(dev->devfn); - func_num = PCI_FUNC(dev->devfn); - printk(" Device %2d: ", slot_num); switch (slot_num) { case 0: - printk("[onboard] Acer Labs M1533 Aladdin IV\n"); dev->irq = nile4_to_irq(NILE4_INT_INTE); break; case 1: - printk("[onboard] DEC DC21140\n"); dev->irq = nile4_to_irq(NILE4_INT_INTA); - dev->resource[0].start = 0x100000; - dev->resource[0].end = dev->resource[0].start+0x7f; - nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, - dev->resource[0].start); - dev->resource[1].start = 0x1000000; - dev->resource[1].end = dev->resource[1].start+0x7f; - nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, - dev->resource[1].start); break; - case 2: - printk("[slot 1] Realtek 8029\n"); + case 2: /* slot 1 */ dev->irq = nile4_to_irq(NILE4_INT_INTA); - dev->resource[0].start = 0x800000; - dev->resource[0].end = dev->resource[0].start+0x1f; - nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, - dev->resource[0].start); break; - case 3: - printk("[slot 2] DEC DC21140 (#2)\n"); + case 3: /* slot 2 */ dev->irq = nile4_to_irq(NILE4_INT_INTB); - dev->resource[0].start = 0x1000000; - dev->resource[0].end = dev->resource[0].start+0x7f; - nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, - dev->resource[0].start); - dev->resource[1].start = 0x4000000; - dev->resource[1].end = dev->resource[1].start+0x7f; - nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, - dev->resource[1].start); break; - case 4: - printk("[slot 3] Promise Technology IDE UltraDMA/33"); - printk(" or 3Com 3c905 :-)\n"); + case 4: /* slot 3 */ dev->irq = nile4_to_irq(NILE4_INT_INTC); - dev->resource[0].start = 0x1800000; - dev->resource[0].end = dev->resource[0].start+0x7fffff; - nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, - dev->resource[0].start); break; case 5: - printk("[onboard] NEC Vrc-5074 Nile 4 Host Bridge\n"); /* * Fixup so the serial driver can use the UART */ dev->irq = nile4_to_irq(NILE4_INT_UART); - dev->resource[0].start = PHYSADDR(NILE4_BASE); - dev->resource[0].end = dev->resource[0].start+NILE4_SIZE-1; - dev->resource[0].flags = IORESOURCE_MEM | - PCI_BASE_ADDRESS_MEM_TYPE_64; - - break; - case 10: - printk("[onboard] Acer Labs M7101 PMU\n"); - pci_pmu = dev; - /* Program the lines for LEDs D2 and D3 to output */ - nile4_pci_read_config_byte(dev, 0x7d, &t8); - t8 |= 0xc0; - nile4_pci_write_config_byte(dev, 0x7d, t8); - /* Turn LEDs D2 and D3 off */ - nile4_pci_read_config_byte(dev, 0x7e, &t8); - t8 |= 0xc0; - nile4_pci_write_config_byte(dev, 0x7e, t8); break; case 13: - printk("[onboard] Acer Labs M5237 USB\n"); dev->irq = nile4_to_irq(NILE4_INT_INTE); - dev->resource[0].start = 0x1001000; - dev->resource[0].end = dev->resource[0].start+0xfff; - nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, - dev->resource[0].start); break; default: - printk("\n"); break; } } } -char *pcibios_setup (char *str) +void __init pcibios_init(void) { - return str; + printk("PCI: Probing PCI hardware\n"); + ioport_resource.end = 0x1ffffff; /* 32 MB */ + iomem_resource.end = 0x1fffffff; /* 512 MB */ + /* `ram' and `nile4' are requested through the Nile4 pci_dev */ + request_resource(&iomem_resource, &ddb5074_resources.flash); + request_resource(&iomem_resource, &ddb5074_resources.isa_io); + request_resource(&iomem_resource, &ddb5074_resources.pci_io); + request_resource(&iomem_resource, &ddb5074_resources.isa_mem); + request_resource(&iomem_resource, &ddb5074_resources.pci_mem); + request_resource(&iomem_resource, &ddb5074_resources.boot); + + pci_scan_bus(0, &nile4_pci_ops, NULL); + ddb5074_pci_fixup(); + pci_assign_unassigned_resources(); + pci_set_bus_ranges(); + pcibios_fixup_irqs(); } -void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) +void __init pcibios_fixup_bus(struct pci_bus *bus) { - unsigned long where, size; - u32 reg; + bus->resource[1] = &ddb5074_resources.pci_mem; +} - where = PCI_BASE_ADDRESS_0 + (resource * 4); - size = res->end - res->start; - pci_read_config_dword(dev, where, ®); - reg = (reg & size) | (((u32)(res->start - root->start)) & ~size); - pci_write_config_dword(dev, where, reg); +char *pcibios_setup (char *str) +{ + return str; } void __init pcibios_update_irq(struct pci_dev *dev, int irq) @@ -341,15 +314,85 @@ ranges->mem_end -= bus->resource[1]->start; } -int __init pcibios_enable_device(struct pci_dev *dev) +int pcibios_enable_resources(struct pci_dev *dev) { - printk("pcibios_enable_device for %04x:%04x\n", dev->vendor, dev->device); - panic("pcibios_enable_device: not yet implemented\n"); + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for(idx=0; idx<6; idx++) { + r = &dev->resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +int pcibios_enable_device(struct pci_dev *dev) +{ + return pcibios_enable_resources(dev); +} + +void pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + u32 new, check; + int reg; + + new = res->start | (res->flags & PCI_REGION_FLAG_MASK); + if (resource < 6) { + reg = PCI_BASE_ADDRESS_0 + 4*resource; + } else if (resource == PCI_ROM_RESOURCE) { + res->flags |= PCI_ROM_ADDRESS_ENABLE; + reg = dev->rom_base_reg; + } else { + /* Somebody might have asked allocation of a non-standard resource */ + return; + } + + pci_write_config_dword(dev, reg, new); + pci_read_config_dword(dev, reg, &check); + if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { + printk(KERN_ERR "PCI: Error while updating region " + "%s/%d (%08x != %08x)\n", dev->slot_name, resource, + new, check); + } +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size) +{ + struct pci_dev *dev = data; + + if (res->flags & IORESOURCE_IO) { + unsigned long start = res->start; + + /* We need to avoid collisions with `mirrored' VGA ports + and other strange ISA hardware, so we always want the + addresses kilobyte aligned. */ + if (size > 0x100) { + printk(KERN_ERR "PCI: I/O Region %s/%d too large" + " (%ld bytes)\n", dev->slot_name, + dev->resource - res, size); + } + + start = (start + 1024 - 1) & ~(1024 - 1); + res->start = start; + } } -void __init pcibios_align_resource(void *data, struct resource *res, - unsigned long size) -{} struct pci_fixup pcibios_fixups[] = {}; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/prom.c linux/arch/mips/ddb5074/prom.c --- v2.3.99-pre8/linux/arch/mips/ddb5074/prom.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/ddb5074/prom.c Sat May 13 08:29:14 2000 @@ -2,9 +2,9 @@ * arch/mips/ddb5074/prom.c -- NEC DDB Vrc-5074 PROM routines * * Copyright (C) 2000 Geert Uytterhoeven - * Sony Suprastructure Center Europe (SUPC-E), Brussels + * Sony Software Development Center Europe (SDCE), Brussels * - * $Id: prom.c,v 1.2 2000/02/14 17:07:36 ralf Exp $ + * $Id: prom.c,v 1.1 2000/01/26 00:07:44 ralf Exp $ */ #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/setup.c linux/arch/mips/ddb5074/setup.c --- v2.3.99-pre8/linux/arch/mips/ddb5074/setup.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/ddb5074/setup.c Sat May 13 08:29:14 2000 @@ -2,9 +2,9 @@ * arch/mips/ddb5074/setup.c -- NEC DDB Vrc-5074 setup routines * * Copyright (C) 2000 Geert Uytterhoeven - * Sony Suprastructure Center Europe (SUPC-E), Brussels + * Sony Software Development Center Europe (SDCE), Brussels * - * $Id: setup.c,v 1.2 2000/02/14 17:07:36 ralf Exp $ + * $Id: setup.c,v 1.1 2000/01/26 00:07:44 ralf Exp $ */ #include @@ -40,12 +40,12 @@ extern struct rtc_ops ddb_rtc_ops; +static void (*back_to_prom)(void) = (void (*)(void))0xbfc00000; + static void ddb_machine_restart(char *command) { u32 t; - // FIXME: This doesn't seem to work... - printk("Restarting DDB Vrc-5074..."); /* PCI cold reset */ t = nile4_in32(NILE4_PCICTRL+4); t |= 0x40000000; @@ -54,8 +54,8 @@ t = nile4_in32(NILE4_CPUSTAT); t |= 1; nile4_out32(NILE4_CPUSTAT, t); - printk("Restart failed!\n"); - do {} while (1); + /* Call the PROM */ + back_to_prom(); } static void ddb_machine_halt(void) @@ -91,6 +91,8 @@ void __init ddb_setup(void) { + extern int panic_timeout; + irq_setup = ddb_irq_setup; mips_io_port_base = NILE4_PCI_IO_BASE; isa_slot_offset = NILE4_PCI_MEM_BASE; @@ -106,6 +108,9 @@ _machine_power_off = ddb_machine_power_off; rtc_ops = &ddb_rtc_ops; + + /* Reboot on panic */ + panic_timeout = 180; } int __init page_is_ram(unsigned long pagenr) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/time.c linux/arch/mips/ddb5074/time.c --- v2.3.99-pre8/linux/arch/mips/ddb5074/time.c Sat Feb 26 22:31:39 2000 +++ linux/arch/mips/ddb5074/time.c Sat May 13 08:29:14 2000 @@ -1,8 +1,8 @@ /* - * arch.mips/ddb5074/time.c -- Timer routines + * arch/mips/ddb5074/time.c -- Timer routines * * Copyright (C) 2000 Geert Uytterhoeven - * Sony Suprastructure Center Europe (SUPC-E), Brussels + * Sony Software Development Center Europe (SDCE), Brussels * * $Id* */ diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/dec/irq.c linux/arch/mips/dec/irq.c --- v2.3.99-pre8/linux/arch/mips/dec/irq.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/dec/irq.c Sat May 13 08:29:14 2000 @@ -31,6 +31,8 @@ extern volatile unsigned int *imr; /* address of the interrupt mask register */ extern decint_t dec_interrupt[NR_INTS]; +irq_cpustat_t irq_stat [NR_CPUS]; + unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/dec/prom/Makefile linux/arch/mips/dec/prom/Makefile --- v2.3.99-pre8/linux/arch/mips/dec/prom/Makefile Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/dec/prom/Makefile Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.2 2000/02/05 06:47:08 ralf Exp $ +# $Id: Makefile,v 1.1 1999/01/17 03:49:44 ralf Exp $ # Makefile for the DECstation prom monitor library routines # under Linux. # diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/dec/prom/init.c linux/arch/mips/dec/prom/init.c --- v2.3.99-pre8/linux/arch/mips/dec/prom/init.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/dec/prom/init.c Sat May 13 08:29:14 2000 @@ -3,7 +3,7 @@ * * Copyright (C) 1998 Harald Koerfgen * - * $Id: init.c,v 1.4 1999/10/09 00:00:58 ralf Exp $ + * $Id: init.c,v 1.3 1999/08/09 19:43:13 harald Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/dec/prom/memory.c linux/arch/mips/dec/prom/memory.c --- v2.3.99-pre8/linux/arch/mips/dec/prom/memory.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/dec/prom/memory.c Sat May 13 08:29:14 2000 @@ -3,7 +3,7 @@ * * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine * - * $Id: memory.c,v 1.4 2000/02/13 20:52:05 harald Exp $ + * $Id: memory.c,v 1.3 1999/10/09 00:00:58 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/dec/reset.c linux/arch/mips/dec/reset.c --- v2.3.99-pre8/linux/arch/mips/dec/reset.c Fri Jun 25 17:40:12 1999 +++ linux/arch/mips/dec/reset.c Sat May 13 08:29:14 2000 @@ -1,5 +1,5 @@ /* - * $Id: reset.c,v 1.4 1999/04/11 17:06:16 harald Exp $ + * $Id: $ * * Reset a DECstation machine. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/dec/rtc-dec.c linux/arch/mips/dec/rtc-dec.c --- v2.3.99-pre8/linux/arch/mips/dec/rtc-dec.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/dec/rtc-dec.c Sat May 13 08:29:14 2000 @@ -1,5 +1,5 @@ -/* $Id: rtc-dec.c,v 1.1 1999/01/17 03:49:42 ralf Exp $ +/* $Id: rtc-jazz.c,v 1.2 1998/06/25 20:19:14 ralf Exp $ * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/dec/serial.c linux/arch/mips/dec/serial.c --- v2.3.99-pre8/linux/arch/mips/dec/serial.c Tue Aug 31 17:29:12 1999 +++ linux/arch/mips/dec/serial.c Sat May 13 08:29:14 2000 @@ -31,11 +31,11 @@ #ifdef CONFIG_SERIAL_CONSOLE #ifdef CONFIG_ZS -extern long zs_serial_console_init(long, long); +extern void zs_serial_console_init(void); #endif #ifdef CONFIG_DZ -extern long dz_serial_console_init(long, long); +extern void dz_serial_console_init(void); #endif #endif @@ -66,6 +66,8 @@ #endif } +__initcall(rs_init); + #endif #ifdef CONFIG_SERIAL_CONSOLE @@ -73,26 +75,24 @@ /* serial_console_init handles the special case of starting * up the console on the serial port */ -long __init serial_console_init(long kmem_start, long kmem_end) +void __init serial_console_init(void) { #if defined(CONFIG_ZS) && defined(CONFIG_DZ) if (IOASIC) - kmem_start = zs_serial_console_init(kmem_start, kmem_end); + zs_serial_console_init(); else - kmem_start = dz_serial_console_init(kmem_start, kmem_end); + dz_serial_console_init(); #else #ifdef CONFIG_ZS - kmem_start = zs_serial_console_init(kmem_start, kmem_end); + zs_serial_console_init(); #endif #ifdef CONFIG_DZ - kmem_start = dz_serial_console_init(kmem_start, kmem_end); + dz_serial_console_init(); #endif #endif - - return kmem_start; } #endif diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/defconfig linux/arch/mips/defconfig --- v2.3.99-pre8/linux/arch/mips/defconfig Thu May 11 15:30:06 2000 +++ linux/arch/mips/defconfig Sat May 13 08:29:14 2000 @@ -20,8 +20,9 @@ CONFIG_SGI_IP22=y # CONFIG_SNI_RM200_PCI is not set # CONFIG_SBUS is not set -# CONFIG_PCI is not set +CONFIG_ARC32=y # CONFIG_ISA is not set +# CONFIG_PCI is not set # # CPU selection @@ -50,24 +51,18 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_NET=y -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # -# Loadable module support +# Parallel port support # +# CONFIG_PARPORT is not set CONFIG_MODULES=y # CONFIG_MODVERSIONS is not set CONFIG_KMOD=y - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set +# CONFIG_PCMCIA is not set # # Block devices @@ -75,14 +70,21 @@ # CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set # # Additional Block Devices # # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_RAID15_DANGEROUS is not set # CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set # # Networking options @@ -134,13 +136,6 @@ # CONFIG_NET_SCHED is not set # -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set - -# # SCSI support # CONFIG_SCSI=y @@ -174,12 +169,12 @@ # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_IPS is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA is not set # CONFIG_SCSI_EATA_DMA is not set @@ -187,155 +182,39 @@ # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_PSI240I is not set # CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SEAGATE is not set # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set # CONFIG_SCSI_DEBUG is not set # # Network device support # CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_NET_SB1000 is not set - -# -# Ethernet (10 or 100Mbit) -# -# CONFIG_NET_ETHERNET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_YELLOWFIN is not set -# CONFIG_ACENIC is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set -# CONFIG_PPP is not set # CONFIG_SLIP is not set +# CONFIG_PPP is not set +CONFIG_SGISEEQ=y # -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# AX.25 network device drivers -# -# CONFIG_MKISS is not set -# CONFIG_6PACK is not set -# CONFIG_BPQETHER is not set -# CONFIG_DMASCC is not set -# CONFIG_SCC is not set -# CONFIG_BAYCOM_SER_FDX is not set -# CONFIG_BAYCOM_SER_HDX is not set -# CONFIG_BAYCOM_PAR is not set -# CONFIG_BAYCOM_EPP is not set -# CONFIG_SOUNDMODEM is not set -# CONFIG_YAM is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Character devices +# SGI Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_SGI_NEWPORT_CONSOLE=y +CONFIG_FONT_8x16=y +# CONFIG_SGI_PROM_CONSOLE is not set # CONFIG_UNIX98_PTYS is not set -# CONFIG_PRINTER is not set -# CONFIG_PPDEV is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set - -# -# Joysticks -# -# CONFIG_JOYSTICK is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set -# CONFIG_AGP is not set - -# -# USB support -# -# CONFIG_USB is not set # # File systems @@ -344,6 +223,7 @@ CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y # CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set @@ -353,10 +233,12 @@ # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set @@ -364,17 +246,22 @@ # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set @@ -382,6 +269,16 @@ CONFIG_LOCKD=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types @@ -392,16 +289,25 @@ # CONFIG_AMIGA_PARTITION is not set # CONFIG_ATARI_PARTITION is not set # CONFIG_MAC_PARTITION is not set -# CONFIG_MSDOS_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_NLS is not set # # Console drivers # -CONFIG_SGI_NEWPORT_CONSOLE=y -CONFIG_FONT_8x16=y +# CONFIG_VGA_CONSOLE is not set +# CONFIG_FB is not set + +# +# Frame-buffer support +# +# CONFIG_FB is not set # # Sound @@ -412,8 +318,14 @@ # SGI devices # CONFIG_SGI_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set CONFIG_SGI_DS1286=y # CONFIG_SGI_NEWPORT_GFX is not set + +# +# USB support +# +# CONFIG_USB is not set # # Kernel hacking diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/defconfig-decstation linux/arch/mips/defconfig-decstation --- v2.3.99-pre8/linux/arch/mips/defconfig-decstation Fri Mar 10 16:40:40 2000 +++ linux/arch/mips/defconfig-decstation Sat May 13 08:29:14 2000 @@ -1,5 +1,5 @@ # -# Automatically generated by make menuconfig: don't edit +# Automatically generated make config: don't edit # # @@ -19,6 +19,9 @@ # CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI_IP22 is not set # CONFIG_SNI_RM200_PCI is not set +# CONFIG_SBUS is not set +# CONFIG_ISA is not set +# CONFIG_PCI is not set # # CPU selection @@ -45,47 +48,41 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_NET=y - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # -# Loadable module support +# Parallel port support # +# CONFIG_PARPORT is not set CONFIG_MODULES=y # CONFIG_MODVERSIONS is not set CONFIG_KMOD=y - -# -# TURBOchannel support -# CONFIG_TC=y +# CONFIG_PCMCIA is not set # -# Plug and Play configuration +# Block devices # -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set # -# Block devices +# Additional Block Devices # -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_IDE is not set -# CONFIG_BLK_DEV_HD_ONLY is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_RAID15_DANGEROUS is not set # CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set +# CONFIG_BLK_DEV_INITRD is not set # # Networking options @@ -107,10 +104,18 @@ # CONFIG_NET_IPGRE is not set # CONFIG_IP_ALIAS is not set # CONFIG_SYN_COOKIES is not set + +# +# (it is safe to leave these untouched) +# # CONFIG_SKB_LARGE is not set # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set # CONFIG_ATM is not set + +# +# +# # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set @@ -129,33 +134,65 @@ # CONFIG_NET_SCHED is not set # -# Telephony Support +# SCSI support # -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set +CONFIG_SCSI=y # -# SCSI support +# SCSI support type (disk, tape, CD-ROM) # -CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 # CONFIG_CHR_DEV_ST is not set # CONFIG_BLK_DEV_SR is not set # CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_DECNCR=y -# CONFIG_SCSI_DECSII is not set +# CONFIG_SCSI_LOGGING is not set # -# I2O device support +# SCSI low-level drivers # -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set +CONFIG_SCSI_DECNCR=y +# CONFIG_SCSI_DECSII is not set +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_DEBUG is not set # # Network device support @@ -167,7 +204,7 @@ CONFIG_DECLANCE=y # -# DECstation Character devices +# DECStation Character devices # # CONFIG_VT is not set CONFIG_SERIAL=y @@ -177,29 +214,26 @@ # CONFIG_UNIX98_PTYS is not set # CONFIG_KEYBOARD is not set # CONFIG_MOUSE is not set +# CONFIG_RTC is not set # -# USB support -# -# CONFIG_USB is not set - -# -# Filesystems +# File systems # # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_BFS_FS_WRITE is not set # CONFIG_FAT_FS is not set # CONFIG_MSDOS_FS is not set # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set @@ -207,6 +241,9 @@ # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set # CONFIG_QNX4FS_RW is not set @@ -224,6 +261,7 @@ # # CONFIG_CODA_FS is not set # CONFIG_NFS_FS is not set +# CONFIG_NFS_V3 is not set # CONFIG_ROOT_NFS is not set # CONFIG_NFSD is not set # CONFIG_NFSD_V3 is not set @@ -231,6 +269,16 @@ # CONFIG_LOCKD is not set # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types @@ -249,6 +297,11 @@ CONFIG_ULTRIX_PARTITION=y # CONFIG_SUN_PARTITION is not set # CONFIG_NLS is not set + +# +# USB support +# +# CONFIG_USB is not set # # Kernel hacking diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/defconfig-ip22 linux/arch/mips/defconfig-ip22 --- v2.3.99-pre8/linux/arch/mips/defconfig-ip22 Thu May 11 15:30:06 2000 +++ linux/arch/mips/defconfig-ip22 Sat May 13 08:29:14 2000 @@ -19,6 +19,10 @@ # CONFIG_OLIVETTI_M700 is not set CONFIG_SGI_IP22=y # CONFIG_SNI_RM200_PCI is not set +# CONFIG_SBUS is not set +CONFIG_ARC32=y +# CONFIG_ISA is not set +# CONFIG_PCI is not set # # CPU selection @@ -47,50 +51,40 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set CONFIG_NET=y - -# -# PCMCIA/CardBus support -# -# CONFIG_PCMCIA is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # -# Loadable module support +# Parallel port support # +# CONFIG_PARPORT is not set CONFIG_MODULES=y # CONFIG_MODVERSIONS is not set CONFIG_KMOD=y - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set +# CONFIG_PCMCIA is not set # # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_IDE is not set - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_ONLY is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set # # Additional Block Devices # # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_RAID15_DANGEROUS is not set # CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set +# CONFIG_BLK_DEV_INITRD is not set # # Networking options @@ -142,12 +136,6 @@ # CONFIG_NET_SCHED is not set # -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set - -# # SCSI support # CONFIG_SCSI=y @@ -158,7 +146,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=y -CONFIG_ST_EXTRA_DEVS=2 CONFIG_BLK_DEV_SR=y # CONFIG_BLK_DEV_SR_VENDOR is not set CONFIG_SR_EXTRA_DEVS=2 @@ -182,12 +169,12 @@ # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_IPS is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA is not set # CONFIG_SCSI_EATA_DMA is not set @@ -195,32 +182,20 @@ # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_PPA is not set -# CONFIG_SCSI_IMM is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_PSI240I is not set # CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SEAGATE is not set # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set # CONFIG_SCSI_DEBUG is not set -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set # # Network device support @@ -232,64 +207,14 @@ CONFIG_SGISEEQ=y # -# Character devices +# SGI Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_SGI_NEWPORT_CONSOLE=y +CONFIG_FONT_8x16=y +# CONFIG_SGI_PROM_CONSOLE is not set # CONFIG_UNIX98_PTYS is not set -# CONFIG_PRINTER is not set -# CONFIG_PPDEV is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set - -# -# Joysticks -# -# CONFIG_JOYSTICK is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set -# CONFIG_AGP is not set - -# -# USB support -# -# CONFIG_USB is not set # # File systems @@ -298,6 +223,7 @@ CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y # CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set @@ -307,10 +233,12 @@ # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set @@ -318,17 +246,22 @@ # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set @@ -336,19 +269,45 @@ CONFIG_LOCKD=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types # -# CONFIG_PARTITION_ADVANCED is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set # CONFIG_NLS is not set # # Console drivers # -CONFIG_SGI_NEWPORT_CONSOLE=y -CONFIG_FONT_8x16=y +# CONFIG_VGA_CONSOLE is not set +# CONFIG_FB is not set + +# +# Frame-buffer support +# +# CONFIG_FB is not set # # Sound @@ -359,8 +318,14 @@ # SGI devices # CONFIG_SGI_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set CONFIG_SGI_DS1286=y # CONFIG_SGI_NEWPORT_GFX is not set + +# +# USB support +# +# CONFIG_USB is not set # # Kernel hacking diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/jazz/Makefile linux/arch/mips/jazz/Makefile --- v2.3.99-pre8/linux/arch/mips/jazz/Makefile Fri Jun 25 17:40:12 1999 +++ linux/arch/mips/jazz/Makefile Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.6 1999/02/25 21:57:01 tsbogend Exp $ +# $Id: Makefile,v 1.5 1999/01/03 17:50:47 ralf Exp $ # # Makefile for the Jazz family specific parts of the kernel # diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/jazz/floppy-jazz.c linux/arch/mips/jazz/floppy-jazz.c --- v2.3.99-pre8/linux/arch/mips/jazz/floppy-jazz.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/jazz/floppy-jazz.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: floppy-jazz.c,v 1.3 2000/02/24 00:12:40 ralf Exp $ +/* $Id: floppy-jazz.c,v 1.2 1998/10/18 13:18:25 tsbogend Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/jazz/int-handler.S linux/arch/mips/jazz/int-handler.S --- v2.3.99-pre8/linux/arch/mips/jazz/int-handler.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/jazz/int-handler.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: int-handler.S,v 1.15 1999/08/18 23:37:43 ralf Exp $ +/* $Id: int-handler.S,v 1.14 1999/05/01 22:40:34 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/jazz/kbd-jazz.c linux/arch/mips/jazz/kbd-jazz.c --- v2.3.99-pre8/linux/arch/mips/jazz/kbd-jazz.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/jazz/kbd-jazz.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: kbd-jazz.c,v 1.1 1999/01/03 17:50:48 ralf Exp $ +/* $Id: kbd-jazz.c,v 1.1 1998/10/28 12:38:10 ralf Exp $ * * Low-level hardware access stuff for Jazz family machines. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/jazz/reset.c linux/arch/mips/jazz/reset.c --- v2.3.99-pre8/linux/arch/mips/jazz/reset.c Fri Jun 25 17:40:12 1999 +++ linux/arch/mips/jazz/reset.c Sat May 13 08:29:14 2000 @@ -3,7 +3,7 @@ * * Reset a Jazz machine. * - * $Id: reset.c,v 1.3 1998/03/04 08:29:10 ralf Exp $ + * $Id:$ */ #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/jazz/rtc-jazz.c linux/arch/mips/jazz/rtc-jazz.c --- v2.3.99-pre8/linux/arch/mips/jazz/rtc-jazz.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/jazz/rtc-jazz.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: rtc-jazz.c,v 1.2 1998/08/26 21:46:38 tsbogend Exp $ +/* $Id: rtc-jazz.c,v 1.2 1998/06/25 20:19:14 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/jazz/setup.c linux/arch/mips/jazz/setup.c --- v2.3.99-pre8/linux/arch/mips/jazz/setup.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/jazz/setup.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.25 2000/01/27 01:05:23 ralf Exp $ +/* $Id: setup.c,v 1.24 1999/10/09 00:00:58 ralf Exp $ * * Setup pointers to hardware-dependent routines. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/Makefile linux/arch/mips/kernel/Makefile --- v2.3.99-pre8/linux/arch/mips/kernel/Makefile Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/Makefile Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.15 2000/01/26 00:07:44 ralf Exp $ +# $Id: Makefile,v 1.14 1999/10/09 00:00:58 ralf Exp $ # # Makefile for the Linux/MIPS kernel. # diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/entry.S linux/arch/mips/kernel/entry.S --- v2.3.99-pre8/linux/arch/mips/kernel/entry.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/entry.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.20 2000/02/23 00:41:00 ralf Exp $ +/* $Id: entry.S,v 1.19 1999/12/08 22:05:10 harald Exp $ * * Low level exception handling * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/fpe.c linux/arch/mips/kernel/fpe.c --- v2.3.99-pre8/linux/arch/mips/kernel/fpe.c Fri Jun 25 17:40:12 1999 +++ linux/arch/mips/kernel/fpe.c Sat May 13 08:29:14 2000 @@ -6,7 +6,7 @@ * * Copyright (C) 1997 Ralf Baechle * - * $Id: fpe.c,v 1.4 1999/05/01 22:40:35 ralf Exp $ + * $Id: fpe.c,v 1.3 1998/04/05 11:23:50 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/gdb-low.S linux/arch/mips/kernel/gdb-low.S --- v2.3.99-pre8/linux/arch/mips/kernel/gdb-low.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/gdb-low.S Sat May 13 08:29:14 2000 @@ -5,7 +5,7 @@ * * Copyright (C) 1995 Andreas Busse * - * $Id: gdb-low.S,v 1.5 1999/08/18 23:37:43 ralf Exp $ + * $Id: gdb-low.S,v 1.4 1997/12/01 17:57:26 ralf Exp $ */ #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c --- v2.3.99-pre8/linux/arch/mips/kernel/gdb-stub.c Fri Jun 25 17:40:12 1999 +++ linux/arch/mips/kernel/gdb-stub.c Sat May 13 08:29:14 2000 @@ -12,7 +12,7 @@ * * Copyright (C) 1995 Andreas Busse * - * $Id: gdb-stub.c,v 1.7 1999/06/12 18:39:28 ulfc Exp $ + * $Id: gdb-stub.c,v 1.6 1999/05/01 22:40:35 ralf Exp $ */ /* diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S --- v2.3.99-pre8/linux/arch/mips/kernel/head.S Thu May 11 15:30:06 2000 +++ linux/arch/mips/kernel/head.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.17 1999/12/04 03:58:59 ralf Exp $ +/* $Id: head.S,v 1.18 2000/03/03 22:17:07 kevink Exp $ * * arch/mips/kernel/head.S * @@ -29,7 +29,6 @@ #include #include #include -#include .text /* @@ -101,7 +100,7 @@ eret END(except_vec0_r4600) - /* TLB refill, EXL == 0, R4xx0, non-R4600 version */ + /* TLB refill, EXL == 0, R52x0 "Nevada" version */ .set noreorder .set noat LEAF(except_vec0_nevada) @@ -122,9 +121,10 @@ mtc0 k0, CP0_ENTRYLO0 # load it srl k1, k1, 6 # convert to entrylo1 mtc0 k1, CP0_ENTRYLO1 # load it - tlbwr # write random tlb entry - nop + nop # QED specified nops nop + tlbwr # write random tlb entry + nop # traditional nop eret # return from trap END(except_vec0_nevada) @@ -393,12 +393,6 @@ EXPORT(stext) EXPORT(_stext) - /* Determine which MIPS variant we are running on. */ - b cpu_probe - nop - -probe_done: - /* * Stack for kernel and init, current variable */ @@ -420,166 +414,9 @@ bne t0, t1, 1b sw zero, (t0) - jal prom_init /* prom_init(argc, argv, envp); */ - nop -#ifdef CONFIG_SGI_IP22 - jal sgi_sysinit - nop -#endif - -#ifdef CONFIG_COBALT_MICRO_SERVER - jal SetUpBootInfo - nop -#endif - - /* - * Determine the mmu/cache attached to this machine, - * then flush the tlb and caches. On the r4xx0 - * variants this also sets CP0_WIRED to zero. - */ - jal loadmmu + jal init_arch nop - - /* Disable coprocessors */ - mfc0 t0, CP0_STATUS - li t1, ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX) - and t0, t1 - or t0, ST0_CU0 - mtc0 t0, CP0_STATUS - -1: jal start_kernel - nop - /* - * Main should never return here, but - * just in case, we know what happens. - */ - b 1b - nop # delay slot END(kernel_entry) - - /* CPU type probing code, called at Kernel entry. */ - LEAF(cpu_probe) - mfc0 t0, CP0_PRID - la t3, mips_cputype - andi t1, t0, 0xff00 - li t2, PRID_IMP_R2000 - bne t1, t2, 1f - andi t0, 0x00ff - - li t2, CPU_R2000 - b probe_done - sw t2, (t3) -1: - li t2, PRID_IMP_R3000 - bne t1, t2, 1f - nop - - li t2, PRID_REV_R3000A - bne t0, t2, 9f - nop - - li t2, CPU_R3000A - b probe_done - sw t2, (t3) -9: - li t2, CPU_R3000 - b probe_done - sw t2, (t3) -1: - li t2, PRID_IMP_R6000 - bne t1, t2, 1f - nop - - li t2, CPU_R6000 - b probe_done - sw t2, (t3) -1: - li t2, PRID_IMP_R4000 - bne t1, t2, 1f - nop - - li t2, PRID_REV_R4400 - bne t0, t2, 9f - nop - - li t2, CPU_R4400SC - b probe_done - sw t2, (t3) -9: - li t2, CPU_R4000SC - b probe_done - sw t2, (t3) -1: - li t2, PRID_IMP_R6000A - bne t1, t2, 1f - nop - - li t2, CPU_R6000A - b probe_done - sw t2, (t3) -1: - li t2, PRID_IMP_R10000 - bne t1, t2, 1f - nop - - li t2, CPU_R10000 - b probe_done - sw t2, (t3) -1: - li t2, PRID_IMP_R8000 - bne t1, t2, 1f - nop - - li t2, CPU_R8000 - b probe_done - sw t2, (t3) -1: - li t2, PRID_IMP_R4600 - bne t1, t2, 1f - nop - - li t2, CPU_R4600 - b probe_done - sw t2, (t3) -1: - li t2, PRID_IMP_R4700 - bne t1, t2, 1f - nop - - li t2, CPU_R4700 - b probe_done - sw t2, (t3) -1: - li t2, PRID_IMP_R4650 - bne t1, t2, 1f - nop - - li t2, CPU_R4650 - b probe_done - sw t2, (t3) -1: - li t2, PRID_IMP_R5000 - bne t1, t2, 1f - nop - - li t2, CPU_R5000 - b probe_done - sw t2, (t3) -1: - li t2, PRID_IMP_NEVADA - bne t1, t2, 1f - nop - - li t2, CPU_NEVADA - b probe_done - sw t2, (t3) -1: - li t2, CPU_UNKNOWN - sw t2, (t3) - - b probe_done - nop - END(cpu_probe) /* * This buffer is reserved for the use of the cache error handler. diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/irix5sys.h linux/arch/mips/kernel/irix5sys.h --- v2.3.99-pre8/linux/arch/mips/kernel/irix5sys.h Fri Jun 25 17:40:12 1999 +++ linux/arch/mips/kernel/irix5sys.h Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: irix5sys.h,v 1.2 1998/08/25 09:14:39 ralf Exp $ +/* $Id: irix5sys.h,v 1.2 1998/08/17 10:16:25 ralf Exp $ * * irix5sys.h: 32-bit IRIX5 ABI system call table. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c --- v2.3.99-pre8/linux/arch/mips/kernel/irixelf.c Wed Apr 26 16:34:06 2000 +++ linux/arch/mips/kernel/irixelf.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: irixelf.c,v 1.24 2000/02/04 07:40:23 ralf Exp $ +/* $Id: irixelf.c,v 1.28 2000/03/23 02:25:42 ralf Exp $ * * irixelf.c: Code to load IRIX ELF executables which conform to * the MIPS ABI. @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -253,10 +254,10 @@ #endif /* First of all, some simple consistency checks */ - if((interp_elf_ex->e_type != ET_EXEC && - interp_elf_ex->e_type != ET_DYN) || - !elf_check_arch(interp_elf_ex->e_machine) || - !interpreter->f_op->mmap) { + if ((interp_elf_ex->e_type != ET_EXEC && + interp_elf_ex->e_type != ET_DYN) || + !elf_check_arch(interp_elf_ex->e_machine) || + !interpreter->f_op->mmap) { printk("IRIX interp has bad e_type %d\n", interp_elf_ex->e_type); return 0xffffffff; } @@ -424,42 +425,41 @@ struct elf_phdr *epp, struct linux_binprm *bprm, int pnum) { - mm_segment_t old_fs; int i; int retval = -EINVAL; struct file *file = NULL; *name = NULL; for(i = 0; i < pnum; i++, epp++) { - if(epp->p_type != PT_INTERP) + if (epp->p_type != PT_INTERP) continue; /* It is illegal to have two interpreters for one executable. */ - if(*name != NULL) + if (*name != NULL) goto out; *name = (char *) kmalloc((epp->p_filesz + strlen(IRIX_INTERP_PREFIX)), GFP_KERNEL); - if(!*name) + if (!*name) return -ENOMEM; strcpy(*name, IRIX_INTERP_PREFIX); retval = kernel_read(bprm->file, epp->p_offset, (*name + 16), - epp->p_filesz); - if(retval < 0) + epp->p_filesz); + if (retval < 0) goto out; file = open_exec(*name); - if(IS_ERR(file)) { + if (IS_ERR(file)) { retval = PTR_ERR(file); goto out; } retval = kernel_read(file, 0, bprm->buf, 128); - if(retval < 0) + if (retval < 0) goto dput_and_out; - *interp_elf_ex = *((struct elfhdr *) bprm->buf); + *interp_elf_ex = *(struct elfhdr *) bprm->buf; } *interpreter = file; return 0; @@ -548,7 +548,7 @@ fput(interp); - if(*eentry == 0xffffffff) + if (*eentry == 0xffffffff) return -1; } return 0; @@ -655,10 +655,10 @@ &interpreter, &interp_elf_ex, elf_phdata, bprm, elf_ex.e_phnum); - if(retval) + if (retval) goto out_free_file; - if(elf_interpreter) { + if (elf_interpreter) { retval = verify_irix_interpreter(&interp_elf_ex); if(retval) goto out_free_interp; @@ -841,8 +841,8 @@ up(¤t->mm->mmap_sem); k = elf_phdata->p_vaddr + elf_phdata->p_filesz; - if(k > elf_bss) elf_bss = k; - + if (k > elf_bss) elf_bss = k; + if (error != (elf_phdata->p_vaddr & 0xfffff000)) { kfree(elf_phdata); return error; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/irixinv.c linux/arch/mips/kernel/irixinv.c --- v2.3.99-pre8/linux/arch/mips/kernel/irixinv.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/irixinv.c Sat May 13 08:29:14 2000 @@ -5,7 +5,7 @@ * * Miguel de Icaza, 1997. * - * $Id: irixinv.c,v 1.4 1999/10/09 00:00:58 ralf Exp $ + * $Id: irixinv.c,v 1.3 1998/04/05 11:23:51 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/irixioctl.c linux/arch/mips/kernel/irixioctl.c --- v2.3.99-pre8/linux/arch/mips/kernel/irixioctl.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/irixioctl.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: irixioctl.c,v 1.7 1999/09/28 22:25:46 ralf Exp $ +/* $Id: irixioctl.c,v 1.6 1999/02/06 05:12:56 adevries Exp $ * irixioctl.c: A fucking mess... * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c --- v2.3.99-pre8/linux/arch/mips/kernel/irixsig.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/irixsig.c Sat May 13 08:29:14 2000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: irixsig.c,v 1.14 2000/01/17 03:58:59 ralf Exp $ + * $Id: irixsig.c,v 1.13 1999/10/09 00:00:58 ralf Exp $ */ #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c --- v2.3.99-pre8/linux/arch/mips/kernel/irq.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/irq.c Sat May 13 08:29:14 2000 @@ -32,6 +32,24 @@ #include /* + * Linux has a controller-independent x86 interrupt architecture. + * every controller has a 'controller-template', that is used + * by the main code to do the right thing. Each driver-visible + * interrupt source is transparently wired to the apropriate + * controller. Thus drivers need not be aware of the + * interrupt-controller. + * + * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, + * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. + * (IO-APICs assumed to be messaging to Pentium local-APICs) + * + * the code is designed to be easily extended with new/different + * interrupt controllers, without having to do assembly magic. + */ + +irq_cpustat_t irq_stat [NR_CPUS]; + +/* * This contains the irq mask for both 8259A irq controllers, it's an * int so we can deal with the third PIC in some systems like the RM300. * (XXX This is broken for big endian.) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c --- v2.3.99-pre8/linux/arch/mips/kernel/mips_ksyms.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/mips_ksyms.c Sat May 13 08:29:14 2000 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -56,8 +57,6 @@ EXPORT_SYMBOL_NOVERS(strpbrk); EXPORT_SYMBOL(_clear_page); -EXPORT_SYMBOL(local_bh_count); -EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(kernel_thread); @@ -87,6 +86,13 @@ EXPORT_SYMBOL(_dma_cache_inv); EXPORT_SYMBOL(invalid_pte_table); + +/* + * Semaphore stuff + */ +EXPORT_SYMBOL(__down_read); +EXPORT_SYMBOL(__down_write); +EXPORT_SYMBOL(__rwsem_wake); /* * Base address of ports for Intel style I/O. diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/proc.c linux/arch/mips/kernel/proc.c --- v2.3.99-pre8/linux/arch/mips/kernel/proc.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/proc.c Sat May 13 08:29:14 2000 @@ -34,6 +34,7 @@ const char *mach_sgi_names[] = GROUP_SGI_NAMES; const char *mach_cobalt_names[] = GROUP_COBALT_NAMES; const char *mach_nec_ddb_names[] = GROUP_NEC_DDB_NAMES; + const char *mach_baget_names[] = GROUP_BAGET_NAMES; const char **mach_group_to_name[] = { mach_unknown_names, mach_jazz_names, mach_dec_names, @@ -42,7 +43,8 @@ mach_acn_names, mach_sgi_names, mach_cobalt_names, - mach_nec_ddb_names }; + mach_nec_ddb_names, + mach_baget_names }; unsigned int version = read_32bit_cp0_register(CP0_PRID); int len; @@ -68,7 +70,7 @@ len += sprintf(buffer + len, "unaligned accesses\t: %lu\n", unaligned_instructions); len += sprintf(buffer + len, "wait instruction\t: %s\n", - wait_available ? "yes" : "no"); + cpu_wait ? "yes" : "no"); len += sprintf(buffer + len, "microsecond timers\t: %s\n", cyclecounter_available ? "yes" : "no"); len += sprintf(buffer + len, "extra interrupt vector\t: %s\n", @@ -82,4 +84,9 @@ len += sprintf(buffer + len, fmt, 'I', vcei_count); return len; +} + +void init_irq_proc(void) +{ + /* Nothing, for now. */ } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c --- v2.3.99-pre8/linux/arch/mips/kernel/process.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/process.c Sat May 13 08:29:14 2000 @@ -40,10 +40,8 @@ while (1) { while (!current->need_resched) - if (wait_available) - __asm__(".set\tmips3\n\t" - "wait\n\t" - ".set\tmips0"); + if (cpu_wait) + (*cpu_wait)(); schedule(); check_pgt_cache(); } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c --- v2.3.99-pre8/linux/arch/mips/kernel/ptrace.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/ptrace.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: ptrace.c,v 1.18 1999/10/09 00:00:58 ralf Exp $ +/* $Id: ptrace.c,v 1.17 1999/09/28 22:25:47 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -28,7 +28,6 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; - unsigned int flags; int res; extern void save_fp(void*); @@ -49,19 +48,22 @@ res = 0; goto out; } - if (pid == 1) { /* you may not mess with init */ - res = -EPERM; + res = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) goto out; - } - if (!(child = find_task_by_pid(pid))) { - res = -ESRCH; + + res = -EPERM; + if (pid == 1) /* you may not mess with init */ goto out; - } + if (request == PTRACE_ATTACH) { - if (child == current) { - res = -EPERM; - goto out; - } + if (child == current) + goto out_tsk; if ((!child->dumpable || (current->uid != child->euid) || (current->uid != child->suid) || @@ -71,42 +73,34 @@ (current->gid != child->gid) || (!cap_issubset(child->cap_permitted, current->cap_permitted)) || - (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)){ - res = -EPERM; - goto out; - } + (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) + goto out_tsk; /* the same process cannot be attached many times */ if (child->flags & PF_PTRACED) - goto out; + goto out_tsk; child->flags |= PF_PTRACED; - write_lock_irqsave(&tasklist_lock, flags); + write_lock_irq(&tasklist_lock); if (child->p_pptr != current) { REMOVE_LINKS(child); child->p_pptr = current; SET_LINKS(child); } - write_unlock_irqrestore(&tasklist_lock, flags); + write_unlock_irq(&tasklist_lock); send_sig(SIGSTOP, child, 1); res = 0; - goto out; - } - if (!(child->flags & PF_PTRACED)) { - res = -ESRCH; - goto out; + goto out_tsk; } + res = -ESRCH; + if (!(child->flags & PF_PTRACED)) + goto out_tsk; if (child->state != TASK_STOPPED) { - if (request != PTRACE_KILL) { - res = -ESRCH; - goto out; - } - } - if (child->p_pptr != current) { - res = -ESRCH; - goto out; + if (request != PTRACE_KILL) + goto out_tsk; } - + if (child->p_pptr != current) + goto out_tsk; switch (request) { case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { @@ -116,11 +110,11 @@ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); res = -EIO; if (copied != sizeof(tmp)) - goto out; + break; res = put_user(tmp,(unsigned long *) data); goto out; - } + } /* Read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { @@ -189,7 +183,7 @@ res = 0; if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) - goto out; + break; res = -EIO; goto out; @@ -240,23 +234,22 @@ res = -EIO; break; } - goto out; + break; } case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ - if ((unsigned long) data > _NSIG) { - res = -EIO; - goto out; - } + res = -EIO; + if ((unsigned long) data > _NSIG) + break; if (request == PTRACE_SYSCALL) child->flags |= PF_TRACESYS; else child->flags &= ~PF_TRACESYS; child->exit_code = data; wake_up_process(child); - res = data; - goto out; + res = 0; + break; } /* @@ -264,34 +257,35 @@ * perhaps it should be put in the status that it wants to * exit. */ - case PTRACE_KILL: { - if (child->state != TASK_ZOMBIE) { - child->exit_code = SIGKILL; - wake_up_process(child); - } + case PTRACE_KILL: res = 0; - goto out; - } + if (child->state != TASK_ZOMBIE) /* already dead */ + break; + child->exit_code = SIGKILL; + wake_up_process(child); + break; - case PTRACE_DETACH: { /* detach a process that was attached. */ - if ((unsigned long) data > _NSIG) { - res = -EIO; - goto out; - } + case PTRACE_DETACH: /* detach a process that was attached. */ + res = -EIO; + if ((unsigned long) data > _NSIG) + break; child->flags &= ~(PF_PTRACED|PF_TRACESYS); child->exit_code = data; + write_lock_irq(&tasklist_lock); REMOVE_LINKS(child); child->p_pptr = child->p_opptr; SET_LINKS(child); + write_unlock_irq(&tasklist_lock); wake_up_process(child); res = 0; - goto out; - } + break; default: res = -EIO; goto out; } +out_tsk: + free_task_struct(child); out: unlock_kernel(); return res; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/r2300_fpu.S linux/arch/mips/kernel/r2300_fpu.S --- v2.3.99-pre8/linux/arch/mips/kernel/r2300_fpu.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/r2300_fpu.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: r2300_fpu.S,v 1.7 1999/09/28 22:25:47 ralf Exp $ +/* $Id: r2300_fpu.S,v 1.6 1999/08/09 19:43:14 harald Exp $ * * r2300_fpu.S: Save/restore floating point context for signal handlers. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/r2300_switch.S linux/arch/mips/kernel/r2300_switch.S --- v2.3.99-pre8/linux/arch/mips/kernel/r2300_switch.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/r2300_switch.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: r2300_switch.S,v 1.9 1999/10/12 17:33:49 harald Exp $ +/* $Id: r2300_switch.S,v 1.8 1999/08/18 23:37:44 ralf Exp $ * * r2300_switch.S: R2300 specific task switching code. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/r4k_fpu.S linux/arch/mips/kernel/r4k_fpu.S --- v2.3.99-pre8/linux/arch/mips/kernel/r4k_fpu.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/r4k_fpu.S Sat May 13 08:29:14 2000 @@ -32,7 +32,6 @@ cfc1 t1,fcr31 /* Store the 16 even double precision registers */ -1: EX(sdc1 $f0,(SC_FPREGS+0)(a0)) EX(sdc1 $f2,(SC_FPREGS+16)(a0)) EX(sdc1 $f4,(SC_FPREGS+32)(a0)) @@ -75,7 +74,7 @@ * Restore the 16 even double precision registers * when cp1 was enabled in the cp0 status register. */ -1: EX(ldc1 $f0,(SC_FPREGS+0)(a0)) + EX(ldc1 $f0,(SC_FPREGS+0)(a0)) EX(ldc1 $f2,(SC_FPREGS+16)(a0)) EX(ldc1 $f4,(SC_FPREGS+32)(a0)) EX(ldc1 $f6,(SC_FPREGS+48)(a0)) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/r4k_misc.S linux/arch/mips/kernel/r4k_misc.S --- v2.3.99-pre8/linux/arch/mips/kernel/r4k_misc.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/r4k_misc.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: r4k_misc.S,v 1.9 1999/12/04 03:59:00 ralf Exp $ +/* $Id: r4k_misc.S,v 1.8 1999/10/09 00:00:58 ralf Exp $ * * r4k_misc.S: Misc. exception handling code for r4k. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/r4k_switch.S linux/arch/mips/kernel/r4k_switch.S --- v2.3.99-pre8/linux/arch/mips/kernel/r4k_switch.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/r4k_switch.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: r4k_switch.S,v 1.10 1999/10/09 00:00:58 ralf Exp $ +/* $Id: r4k_switch.S,v 1.9 1999/08/18 23:37:44 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/r6000_fpu.S linux/arch/mips/kernel/r6000_fpu.S --- v2.3.99-pre8/linux/arch/mips/kernel/r6000_fpu.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/r6000_fpu.S Sat May 13 08:29:14 2000 @@ -10,7 +10,7 @@ * Multi-arch abstraction and asm macros for easier reading: * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: r6000_fpu.S,v 1.6 1999/08/09 19:43:15 harald Exp $ + * $Id: r6000_fpu.S,v 1.5 1999/05/01 22:40:37 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/scall_o32.S linux/arch/mips/kernel/scall_o32.S --- v2.3.99-pre8/linux/arch/mips/kernel/scall_o32.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/scall_o32.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: scall_o32.S,v 1.11 2000/02/23 01:33:55 ralf Exp $ +/* $Id: scall_o32.S,v 1.10 2000/02/23 00:41:00 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c --- v2.3.99-pre8/linux/arch/mips/kernel/setup.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/setup.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.22 2000/01/27 01:05:23 ralf Exp $ +/* $Id: setup.c,v 1.28 2000/03/13 22:21:44 harald Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef CONFIG_SGI_IP22 #include #endif @@ -46,11 +47,13 @@ struct mips_cpuinfo boot_cpu_data = { NULL, NULL, 0 }; /* - * Not all of the MIPS CPUs have the "wait" instruction available. This - * is set to true if it is available. The wait instruction stops the - * pipeline and reduces the power consumption of the CPU very much. + * Not all of the MIPS CPUs have the "wait" instruction available. Moreover, + * the implementation of the "wait" feature differs between CPU families. This + * points to the function that implements CPU specific wait. + * The wait instruction stops the pipeline and reduces the power consumption of + * the CPU very much. */ -char wait_available; +void (*cpu_wait)(void) = NULL; /* * Do we have a cyclecounter available? @@ -119,6 +122,125 @@ */ unsigned long isa_slot_offset; +extern void sgi_sysinit(void); +extern void SetUpBootInfo(void); +extern void loadmmu(void); +extern asmlinkage void start_kernel(void); +extern int prom_init(int, char **, char **, int *); + +/* + * Probe whether cpu has config register by trying to play with + * alternate cache bit and see whether it matters. + * It's used by cpu_probe to distinguish between R3000A and R3081. + */ +static inline int cpu_has_confreg(void) +{ +#ifdef CONFIG_CPU_R3000 + extern unsigned long r3k_cache_size(unsigned long); + unsigned long size1, size2; + unsigned long cfg = read_32bit_cp0_register(CP0_CONF); + + size1 = r3k_cache_size(ST0_DE); + write_32bit_cp0_register(CP0_CONF, cfg^CONF_AC); + size2 = r3k_cache_size(ST0_DE); + write_32bit_cp0_register(CP0_CONF, cfg); + return size1 != size2; +#else + return 0; +#endif +} + +static inline void cpu_probe(void) +{ + unsigned int prid = read_32bit_cp0_register(CP0_PRID); + switch(prid & 0xff00) { + case PRID_IMP_R2000: + mips_cputype = CPU_R2000; + break; + case PRID_IMP_R3000: + if((prid & 0xff) == PRID_REV_R3000A) + if(cpu_has_confreg()) + mips_cputype = CPU_R3081E; + else + mips_cputype = CPU_R3000A; + else + mips_cputype = CPU_R3000; + break; + case PRID_IMP_R4000: + if((prid & 0xff) == PRID_REV_R4400) + mips_cputype = CPU_R4400SC; + else + mips_cputype = CPU_R4000SC; + break; + case PRID_IMP_R4600: + mips_cputype = CPU_R4600; + break; + case PRID_IMP_R4650: + mips_cputype = CPU_R4650; + break; + case PRID_IMP_R4700: + mips_cputype = CPU_R4700; + break; + case PRID_IMP_R5000: + mips_cputype = CPU_R5000; + break; + case PRID_IMP_NEVADA: + mips_cputype = CPU_NEVADA; + break; + case PRID_IMP_R6000: + mips_cputype = CPU_R6000; + break; + case PRID_IMP_R6000A: + mips_cputype = CPU_R6000A; + break; + case PRID_IMP_R8000: + mips_cputype = CPU_R8000; + break; + case PRID_IMP_R10000: + mips_cputype = CPU_R10000; + break; + default: + mips_cputype = CPU_UNKNOWN; + } +} + +asmlinkage void __init init_arch(int argc, char **argv, char **envp, int *prom_vec) +{ + unsigned int s; + + /* Determine which MIPS variant we are running on. */ + cpu_probe(); + + prom_init(argc, argv, envp, prom_vec); + +#ifdef CONFIG_SGI_IP22 + sgi_sysinit(); +#endif +#ifdef CONFIG_COBALT_MICRO_SERVER + SetUpBootInfo(); +#endif + + /* + * Determine the mmu/cache attached to this machine, + * then flush the tlb and caches. On the r4xx0 + * variants this also sets CP0_WIRED to zero. + */ + loadmmu(); + + /* Disable coprocessors */ + s = read_32bit_cp0_register(CP0_STATUS); + s &= ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX); + s |= ST0_CU0; + write_32bit_cp0_register(CP0_STATUS, s); + + /* + * Main should never return here, but + * just in case, we know what happens. + */ + for(;;) + start_kernel(); +} + static void __init default_irq_setup(void) { panic("Unknown machtype in init_IRQ"); @@ -156,7 +278,7 @@ switch(mips_machgroup) { #ifdef CONFIG_BAGET_MIPS - case MACH_GROUP_UNKNOWN: + case MACH_GROUP_BAGET: baget_setup(); break; #endif @@ -220,4 +342,19 @@ *memory_start_p = initrd_end; } #endif + + paging_init(); +} + +void r3081_wait(void) +{ + unsigned long cfg = read_32bit_cp0_register(CP0_CONF); + write_32bit_cp0_register(CP0_CONF, cfg|CONF_HALT); +} + +void r4k_wait(void) +{ + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c --- v2.3.99-pre8/linux/arch/mips/kernel/signal.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/signal.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.25 2000/02/05 06:47:08 ralf Exp $ +/* $Id: signal.c,v 1.24 2000/02/04 07:40:23 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/softfp.S linux/arch/mips/kernel/softfp.S --- v2.3.99-pre8/linux/arch/mips/kernel/softfp.S Fri Jun 25 17:40:12 1999 +++ linux/arch/mips/kernel/softfp.S Sat May 13 08:29:14 2000 @@ -147,7 +147,7 @@ insn: LOCK_KERNEL; \ la a1, 8f; \ TEXT(#insn); \ - la a1, nosim; \ + la a0, nosim; \ UNLOCK_KERNEL; \ j done diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c --- v2.3.99-pre8/linux/arch/mips/kernel/syscall.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/syscall.c Sat May 13 08:29:14 2000 @@ -129,7 +129,6 @@ int error; char * filename; - lock_kernel(); filename = getname((char *) (long)regs.regs[4]); error = PTR_ERR(filename); if (IS_ERR(filename)) @@ -139,7 +138,6 @@ putname(filename); out: - unlock_kernel(); return error; } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h --- v2.3.99-pre8/linux/arch/mips/kernel/syscalls.h Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/syscalls.h Sat May 13 08:29:14 2000 @@ -44,7 +44,7 @@ SYS(sys_ptrace, 4) SYS(sys_alarm, 1) SYS(sys_fstat, 2) -SYS(sys_ni_syscall, 0) +SYS(sys_pause, 0) SYS(sys_utime, 2) /* 4030 */ SYS(sys_ni_syscall, 0) SYS(sys_ni_syscall, 0) @@ -232,3 +232,5 @@ SYS(sys_lstat64, 3) SYS(sys_fstat64, 3) /* 4215 */ SYS(sys_pivot_root, 2) +SYS(sys_mincore, 3) +SYS(sys_madvise, 3) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c --- v2.3.99-pre8/linux/arch/mips/kernel/sysirix.c Thu May 11 15:30:06 2000 +++ linux/arch/mips/kernel/sysirix.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: sysirix.c,v 1.24 2000/02/05 06:47:08 ralf Exp $ +/* $Id: sysirix.c,v 1.26 2000/03/12 23:15:33 ralf Exp $ * * sysirix.c: IRIX system call emulation. * @@ -853,7 +853,6 @@ int error, base = 0; char *filename; - lock_kernel(); if(regs->regs[2] == 1000) base = 1; filename = getname((char *) (long)regs->regs[base + 4]); @@ -865,7 +864,6 @@ putname(filename); out: - unlock_kernel(); return error; } @@ -1491,10 +1489,10 @@ printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n", current->comm, current->pid, fname, buf); error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs)); - if(error) + if (error) goto out; error = user_path_walk(fname, &nd); - if (err) + if (error) goto out; error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf); if (error) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c --- v2.3.99-pre8/linux/arch/mips/kernel/sysmips.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/sysmips.c Sat May 13 08:29:14 2000 @@ -7,7 +7,7 @@ * * Copyright (C) 1995, 1996, 1997 by Ralf Baechle * - * $Id: sysmips.c,v 1.9 2000/02/18 00:24:30 ralf Exp $ + * $Id: sysmips.c,v 1.8 2000/02/05 06:47:08 ralf Exp $ */ #include #include @@ -123,4 +123,11 @@ sys_cachectl(char *addr, int nbytes, int op) { return -ENOSYS; +} + +asmlinkage int sys_pause(void) +{ + current->state = TASK_INTERRUPTIBLE; + schedule(); + return -ERESTARTNOHAND; } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c --- v2.3.99-pre8/linux/arch/mips/kernel/traps.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/traps.c Sat May 13 08:29:14 2000 @@ -1,12 +1,13 @@ -/* $Id: traps.c,v 1.27 2000/01/16 01:29:05 ralf Exp $ +/* $Id: traps.c,v 1.28 2000/03/13 10:33:02 raiko Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright 1994, 1995, 1996, 1997, 1998 by Ralf Baechle + * Copyright (C) 1994 - 1999 by Ralf Baechle * Modified for R3000 by Paul M. Antoine, 1995, 1996 * Complete output from die() by Ulf Carlsson, 1998 + * Copyright (C) 1999 Silicon Graphics, Inc. */ #include #include @@ -226,8 +227,50 @@ __die(str, regs, where, line); } +extern const struct exception_table_entry __start___dbe_table[]; +extern const struct exception_table_entry __stop___dbe_table[]; + +static void __declare_dbe_table(void) +{ + __asm__ __volatile__( + ".section\t__dbe_table,\"a\"\n\t" + ".previous" + ); +} + +static inline unsigned long +search_one_table(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value) +{ + const struct exception_table_entry *mid; + long diff; + + while (first < last) { + mid = (last - first) / 2 + first; + diff = mid->insn - value; + if (diff < 0) + first = mid + 1; + else + last = mid; + } + return (first == last && first->insn == value) ? first->nextinsn : 0; +} + +#define search_dbe_table(addr) \ + search_one_table(__start___dbe_table, __stop___dbe_table - 1, (addr)) + static void default_be_board_handler(struct pt_regs *regs) { + unsigned long new_epc; + unsigned long fixup = search_dbe_table(regs->cp0_epc); + + if (fixup) { + new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); + regs->cp0_epc = new_epc; + return; + } + /* * Assume it would be too dangerous to continue ... */ @@ -281,7 +324,7 @@ { unsigned long pc; unsigned int insn; - extern void simfp(void*); + extern void simfp(unsigned int); #ifdef CONFIG_MIPS_FPE_MODULE if (fpe_handler != NULL) { @@ -688,8 +731,7 @@ else memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); - /* Cache error vector */ - memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80); + /* Cache error vector already set above. */ if (vce_available) { memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, @@ -698,7 +740,6 @@ memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); } - break; case CPU_R6000: @@ -718,14 +759,14 @@ case CPU_R2000: case CPU_R3000: case CPU_R3000A: - memcpy((void *)KSEG0, &except_vec0_r2300, 0x80); - memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80); - break; case CPU_R3041: case CPU_R3051: case CPU_R3052: case CPU_R3081: case CPU_R3081E: + memcpy((void *)KSEG0, &except_vec0_r2300, 0x80); + memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80); + break; case CPU_R8000: printk("Detected unsupported CPU type %s.\n", cpu_names[mips_cputype]); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/unaligned.c linux/arch/mips/kernel/unaligned.c --- v2.3.99-pre8/linux/arch/mips/kernel/unaligned.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/kernel/unaligned.c Sat May 13 08:29:14 2000 @@ -7,8 +7,7 @@ * for more details. * * Copyright (C) 1996, 1998 by Ralf Baechle - * - * $Id: unaligned.c,v 1.7 1999/12/04 03:59:00 ralf Exp $ + * Copyright (C) 1999 Silicon Graphics, Inc. * * This file contains exception handler for address error exception with the * special capability to execute faulting instructions in software. The diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile --- v2.3.99-pre8/linux/arch/mips/lib/Makefile Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/lib/Makefile Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.12 1999/12/04 03:59:00 ralf Exp $ +# $Id: Makefile,v 1.11 1999/10/17 19:55:22 harald Exp $ # # Makefile for MIPS-specific library files.. # diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/csum_partial.S linux/arch/mips/lib/csum_partial.S --- v2.3.99-pre8/linux/arch/mips/lib/csum_partial.S Fri Jun 25 17:40:12 1999 +++ linux/arch/mips/lib/csum_partial.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: csum_partial.S,v 1.2 1998/05/07 23:44:01 ralf Exp $ +/* $Id: csum_partial.S,v 1.1 1998/05/04 09:12:52 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/csum_partial_copy.c linux/arch/mips/lib/csum_partial_copy.c --- v2.3.99-pre8/linux/arch/mips/lib/csum_partial_copy.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/lib/csum_partial_copy.c Sat May 13 08:29:14 2000 @@ -14,7 +14,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * $Id: csum_partial_copy.c,v 1.3 2000/02/05 06:47:08 ralf Exp $ + * $Id: csum_partial_copy.c,v 1.2 1998/09/19 19:16:17 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/floppy-no.c linux/arch/mips/lib/floppy-no.c --- v2.3.99-pre8/linux/arch/mips/lib/floppy-no.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/lib/floppy-no.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: floppy-no.c,v 1.1 1998/06/30 00:21:54 ralf Exp $ +/* $Id: floppy-no.c,v 1.1 1998/05/07 18:38:32 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/floppy-std.c linux/arch/mips/lib/floppy-std.c --- v2.3.99-pre8/linux/arch/mips/lib/floppy-std.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/lib/floppy-std.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: floppy-std.c,v 1.3 2000/02/24 00:12:40 ralf Exp $ +/* $Id: floppy-std.c,v 1.2 1999/01/04 16:03:51 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/ide-no.c linux/arch/mips/lib/ide-no.c --- v2.3.99-pre8/linux/arch/mips/lib/ide-no.c Fri Jun 25 17:40:13 1999 +++ linux/arch/mips/lib/ide-no.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: ide-no.c,v 1.3 1999/06/17 13:25:49 ralf Exp $ +/* $Id: ide-no.c,v 1.2 1998/06/30 00:21:54 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/ide-std.c linux/arch/mips/lib/ide-std.c --- v2.3.99-pre8/linux/arch/mips/lib/ide-std.c Fri Jun 25 17:40:13 1999 +++ linux/arch/mips/lib/ide-std.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: ide-std.c,v 1.4 1999/06/17 13:25:49 ralf Exp $ +/* $Id: ide-std.c,v 1.4 1999/06/11 14:29:45 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/kbd-no.c linux/arch/mips/lib/kbd-no.c --- v2.3.99-pre8/linux/arch/mips/lib/kbd-no.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/lib/kbd-no.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: kbd-no.c,v 1.1 1999/01/04 16:03:51 ralf Exp $ +/* $Id: kbd-no.c,v 1.1 1998/10/28 12:38:14 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/kbd-std.c linux/arch/mips/lib/kbd-std.c --- v2.3.99-pre8/linux/arch/mips/lib/kbd-std.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/lib/kbd-std.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: kbd-std.c,v 1.2 1999/06/17 13:25:50 ralf Exp $ +/* $Id: kbd-std.c,v 1.2 1999/06/11 14:29:45 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/memcpy.S linux/arch/mips/lib/memcpy.S --- v2.3.99-pre8/linux/arch/mips/lib/memcpy.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/lib/memcpy.S Sat May 13 08:29:14 2000 @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * $Id: memcpy.S,v 1.4 2000/01/27 01:05:23 ralf Exp $ + * $Id: memcpy.S,v 1.3 1998/07/10 01:14:49 ralf Exp $ * * Unified implementation of memcpy, memmove and the __copy_user backend. * For __rmemcpy and memmove an exception is always a kernel bug, therefore diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/memset.S linux/arch/mips/lib/memset.S --- v2.3.99-pre8/linux/arch/mips/lib/memset.S Fri Jun 25 17:40:13 1999 +++ linux/arch/mips/lib/memset.S Sat May 13 08:29:14 2000 @@ -7,7 +7,7 @@ * * Copyright (C) 1998 by Ralf Baechle * - * $Id: memset.S,v 1.1 1998/05/04 09:12:54 ralf Exp $ + * $Id: memset.S,v 1.2 1998/04/25 17:01:45 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/r3k_dump_tlb.c linux/arch/mips/lib/r3k_dump_tlb.c --- v2.3.99-pre8/linux/arch/mips/lib/r3k_dump_tlb.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/lib/r3k_dump_tlb.c Sat May 13 08:29:14 2000 @@ -29,7 +29,7 @@ for(i=first;i<=last;i++) { - write_32bit_cp0_register(CP0_INDEX, i); + write_32bit_cp0_register(CP0_INDEX, i<<8); __asm__ __volatile__( ".set\tnoreorder\n\t" "tlbr\n\t" diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/rtc-no.c linux/arch/mips/lib/rtc-no.c --- v2.3.99-pre8/linux/arch/mips/lib/rtc-no.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/lib/rtc-no.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: rtc-no.c,v 1.1 1998/06/30 00:21:55 ralf Exp $ +/* $Id: rtc-no.c,v 1.2 1998/06/25 20:19:15 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/rtc-std.c linux/arch/mips/lib/rtc-std.c --- v2.3.99-pre8/linux/arch/mips/lib/rtc-std.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/lib/rtc-std.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: rtc-std.c,v 1.1 1998/06/30 00:21:55 ralf Exp $ +/* $Id: rtc-std.c,v 1.2 1998/06/25 20:19:16 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/strlen_user.S linux/arch/mips/lib/strlen_user.S --- v2.3.99-pre8/linux/arch/mips/lib/strlen_user.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/lib/strlen_user.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: strlen_user.S,v 1.4 1999/12/04 03:59:00 ralf Exp $ +/* $Id: strlen_user.S,v 1.3 1999/08/21 22:19:11 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/strncpy_user.S linux/arch/mips/lib/strncpy_user.S --- v2.3.99-pre8/linux/arch/mips/lib/strncpy_user.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/lib/strncpy_user.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: strncpy_user.S,v 1.4 1999/12/04 03:59:00 ralf Exp $ +/* $Id: strncpy_user.S,v 1.3 1999/08/21 22:19:11 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/strnlen_user.S linux/arch/mips/lib/strnlen_user.S --- v2.3.99-pre8/linux/arch/mips/lib/strnlen_user.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/lib/strnlen_user.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: strnlen_user.S,v 1.2 1999/12/04 03:59:00 ralf Exp $ +/* $Id: strnlen_user.S,v 1.2 1999/11/19 20:35:21 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/watch.S linux/arch/mips/lib/watch.S --- v2.3.99-pre8/linux/arch/mips/lib/watch.S Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/lib/watch.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: watch.S,v 1.3 1999/08/21 22:19:11 ralf Exp $ +/* $Id$ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/mm/andes.c linux/arch/mips/mm/andes.c --- v2.3.99-pre8/linux/arch/mips/mm/andes.c Sat Feb 26 22:31:40 2000 +++ linux/arch/mips/mm/andes.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: andes.c,v 1.11 2000/02/24 00:12:40 ralf Exp $ +/* $Id: andes.c,v 1.10 2000/02/13 20:52:05 harald Exp $ * * andes.c: MMU and cache operations for the R10000 (ANDES). * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/mm/fault.c linux/arch/mips/mm/fault.c --- v2.3.99-pre8/linux/arch/mips/mm/fault.c Wed Apr 26 16:34:06 2000 +++ linux/arch/mips/mm/fault.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.16 2000/02/18 00:24:30 ralf Exp $ +/* $Id: fault.c,v 1.15 2000/02/04 07:40:23 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -90,12 +90,17 @@ * make sure we exit gracefully rather than endlessly redo * the fault. */ - { - int fault = handle_mm_fault(mm, vma, address, write); - if (fault < 0) - goto out_of_memory; - if (!fault) - goto do_sigbus; + switch (handle_mm_fault(mm, vma, address, write)) { + case 1: + tsk->min_flt++; + break; + case 2: + tsk->maj_flt++; + break; + case 0: + goto do_sigbus; + default: + goto out_of_memory; } up(&mm->mmap_sem); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/mm/init.c linux/arch/mips/mm/init.c --- v2.3.99-pre8/linux/arch/mips/mm/init.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/mm/init.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.27 2000/02/23 01:33:56 ralf Exp $ +/* $Id: init.c,v 1.26 2000/02/23 00:41:00 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/mm/loadmmu.c linux/arch/mips/mm/loadmmu.c --- v2.3.99-pre8/linux/arch/mips/mm/loadmmu.c Thu Mar 2 14:36:22 2000 +++ linux/arch/mips/mm/loadmmu.c Sat May 13 08:29:14 2000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: loadmmu.c,v 1.15 2000/02/24 00:12:40 ralf Exp $ + * $Id: loadmmu.c,v 1.17 2000/03/13 10:33:05 raiko Exp $ */ #include #include @@ -15,7 +15,6 @@ #include #include #include -#include /* memory functions */ void (*_clear_page)(void * page); @@ -59,6 +58,7 @@ case CPU_R2000: case CPU_R3000: case CPU_R3000A: + case CPU_R3081E: printk("Loading R[23]00 MMU routines.\n"); ld_mmu_r2300(); break; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/mm/r2300.c linux/arch/mips/mm/r2300.c --- v2.3.99-pre8/linux/arch/mips/mm/r2300.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/mm/r2300.c Sat May 13 08:29:14 2000 @@ -7,7 +7,7 @@ * Copyright (C) 1998, 2000 Harald Koerfgen * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov * - * $Id: r2300.c,v 1.15 2000/02/24 00:12:40 ralf Exp $ + * $Id: r2300.c,v 1.16 2000/03/13 10:33:05 raiko Exp $ */ #include #include @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -116,7 +115,7 @@ "I" (PAGE_SIZE)); } -static unsigned long __init size_cache(unsigned long ca_flags) +unsigned long __init r3k_cache_size(unsigned long ca_flags) { unsigned long flags, status, dummy, size; volatile unsigned long *p; @@ -152,14 +151,14 @@ static void __init probe_dcache(void) { - dcache_size = size_cache(ST0_DE); + dcache_size = r3k_cache_size(ST0_DE); printk("Primary data cache %dkb, linesize 4 bytes\n", dcache_size >> 10); } static void __init probe_icache(void) { - icache_size = size_cache(ST0_DE|ST0_CE); + icache_size = r3k_cache_size(ST0_DE|ST0_CE); printk("Primary instruction cache %dkb, linesize 8 bytes\n", icache_size >> 10); } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/mm/r4xx0.c linux/arch/mips/mm/r4xx0.c --- v2.3.99-pre8/linux/arch/mips/mm/r4xx0.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/mm/r4xx0.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: r4xx0.c,v 1.30 2000/02/24 01:12:37 ralf Exp $ +/* $Id: r4xx0.c,v 1.29 2000/02/24 00:12:40 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/Makefile linux/arch/mips/sgi/kernel/Makefile --- v2.3.99-pre8/linux/arch/mips/sgi/kernel/Makefile Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sgi/kernel/Makefile Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.8 2000/02/05 06:47:08 ralf Exp $ +# $Id: Makefile,v 1.7 1999/05/07 18:00:16 ulfc Exp $ # Makefile for the SGI specific kernel interface routines # under Linux. # diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/indyIRQ.S linux/arch/mips/sgi/kernel/indyIRQ.S --- v2.3.99-pre8/linux/arch/mips/sgi/kernel/indyIRQ.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sgi/kernel/indyIRQ.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: indyIRQ.S,v 1.4 1999/08/18 23:37:45 ralf Exp $ +/* $Id: indyIRQ.S,v 1.3 1998/03/22 23:27:17 ralf Exp $ * indyIRQ.S: Interrupt exception dispatch code for FullHouse and * Guiness. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_hpc.c linux/arch/mips/sgi/kernel/indy_hpc.c --- v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_hpc.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sgi/kernel/indy_hpc.c Sat May 13 08:29:14 2000 @@ -6,6 +6,7 @@ * Copyright (C) 1998 Ralf Baechle */ #include +#include #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_int.c linux/arch/mips/sgi/kernel/indy_int.c --- v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_int.c Thu Mar 2 14:36:22 2000 +++ linux/arch/mips/sgi/kernel/indy_int.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: indy_int.c,v 1.17 2000/02/04 07:40:23 ralf Exp $ +/* $Id: indy_int.c,v 1.18 2000/03/02 02:36:50 ralf Exp $ * * indy_int.c: Routines for generic manipulation of the INT[23] ASIC * found on INDY workstations.. @@ -38,6 +38,24 @@ #include #include #include + +/* + * Linux has a controller-independent x86 interrupt architecture. + * every controller has a 'controller-template', that is used + * by the main code to do the right thing. Each driver-visible + * interrupt source is transparently wired to the apropriate + * controller. Thus drivers need not be aware of the + * interrupt-controller. + * + * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, + * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. + * (IO-APICs assumed to be messaging to Pentium local-APICs) + * + * the code is designed to be easily extended with new/different + * interrupt controllers, without having to do assembly magic. + */ + +irq_cpustat_t irq_stat [NR_CPUS]; /* #define DEBUG_SGINT */ diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_mc.c linux/arch/mips/sgi/kernel/indy_mc.c --- v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_mc.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sgi/kernel/indy_mc.c Sat May 13 08:29:14 2000 @@ -4,7 +4,7 @@ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - Indigo2 changes * - * $Id: indy_mc.c,v 1.8 1999/12/06 23:13:20 ralf Exp $ + * $Id: indy_mc.c,v 1.7 1999/12/04 03:59:00 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_rtc.c linux/arch/mips/sgi/kernel/indy_rtc.c --- v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_rtc.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sgi/kernel/indy_rtc.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: indy_rtc.c,v 1.2 1999/10/21 00:23:05 ralf Exp $ +/* $Id: indy_rtc.c,v 1.1 1998/06/30 00:21:58 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_sc.c linux/arch/mips/sgi/kernel/indy_sc.c --- v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_sc.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sgi/kernel/indy_sc.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: indy_sc.c,v 1.13 1999/12/04 03:59:00 ralf Exp $ +/* $Id: indy_sc.c,v 1.14 2000/03/25 22:35:07 ralf Exp $ * * indy_sc.c: Indy cache managment functions. * @@ -28,16 +28,17 @@ #define SC_SIZE 0x00080000 #define SC_LINE 32 #define CI_MASK (SC_SIZE - SC_LINE) -#define SC_ROUND(n) ((n) + SC_LINE - 1) #define SC_INDEX(n) ((n) & CI_MASK) static inline void indy_sc_wipe(unsigned long first, unsigned long last) { + unsigned long tmp; + __asm__ __volatile__(" .set noreorder .set mips3 .set noat - mfc0 $2, $12 + mfc0 %2, $12 li $1, 0x80 # Go 64 bit mtc0 $1, $12 @@ -50,12 +51,12 @@ bne %0, %1, 1b daddu %0, 32 - mtc0 $2, $12 # Back to 32 bit + mtc0 %2, $12 # Back to 32 bit nop; nop; nop; nop; .set mips0 .set reorder" - : /* no output */ - : "r" (first), "r" (last) + : "=r" (first), "=r" (last), "=&r" (tmp) + : "0" (first), "1" (last) : "$1"); } @@ -67,12 +68,13 @@ #ifdef DEBUG_CACHE printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size); #endif + + if (!size) + return; + /* Which lines to flush? */ first_line = SC_INDEX(addr); - if (size <= SC_LINE) - last_line = SC_INDEX(addr); - else - last_line = SC_INDEX(addr + size - 1); + last_line = SC_INDEX(addr + size - 1); __save_and_cli(flags); if (first_line <= last_line) { @@ -80,9 +82,6 @@ goto out; } - /* Cache index wrap around. Due to the way the buddy system works - this case should not happen. We're prepared to handle it, - though. */ indy_sc_wipe(first_line, SC_SIZE - SC_LINE); indy_sc_wipe(0, last_line); out: @@ -98,8 +97,9 @@ printk("Enabling R4600 SCACHE\n"); #endif __asm__ __volatile__(" - .set noreorder - .set mips3 + .set push + .set noreorder + .set mips3 mfc0 %2, $12 nop; nop; nop; nop; li %1, 0x80 @@ -115,8 +115,7 @@ nop; nop; nop; nop; mtc0 %2, $12 nop; nop; nop; nop; - .set mips0 - .set reorder" + .set pop" : "=r" (tmp1), "=r" (tmp2), "=r" (addr)); } @@ -128,8 +127,9 @@ printk("Disabling R4600 SCACHE\n"); #endif __asm__ __volatile__(" - .set noreorder - .set mips3 + .set push + .set noreorder + .set mips3 li %0, 0x1 dsll %0, 31 lui %1, 0x9000 @@ -145,9 +145,8 @@ nop; nop; nop; nop; mtc0 %2, $12 nop; nop; nop; nop; - .set mips2 - .set reorder - " : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)); + .set pop" + : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)); } static inline int __init indy_sc_probe(void) @@ -221,7 +220,6 @@ void __init indy_sc_init(void) { -return; if (indy_sc_probe()) { indy_sc_enable(); bcops = &indy_sc_ops; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_timer.c linux/arch/mips/sgi/kernel/indy_timer.c --- v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_timer.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sgi/kernel/indy_timer.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: indy_timer.c,v 1.18 2000/02/04 07:40:23 ralf Exp $ +/* $Id: indy_timer.c,v 1.17 2000/01/21 22:34:03 ralf Exp $ * * indy_timer.c: Setting up the clock on the INDY 8254 controller. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/promcon.c linux/arch/mips/sgi/kernel/promcon.c --- v2.3.99-pre8/linux/arch/mips/sgi/kernel/promcon.c Tue Aug 31 17:29:12 1999 +++ linux/arch/mips/sgi/kernel/promcon.c Sat May 13 08:29:14 2000 @@ -66,8 +66,7 @@ * Register console. */ -long __init sgi_prom_console_init(long kmem_start, long kmem_end) +void __init sgi_prom_console_init(void ) { register_console(&sercons); - return kmem_start; } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/reset.c linux/arch/mips/sgi/kernel/reset.c --- v2.3.99-pre8/linux/arch/mips/sgi/kernel/reset.c Thu May 11 15:30:06 2000 +++ linux/arch/mips/sgi/kernel/reset.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: reset.c,v 1.8 1999/10/21 00:23:05 ralf Exp $ +/* $Id: reset.c,v 1.7 1999/08/11 20:26:51 andrewb Exp $ * * Reset a SGI. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/setup.c linux/arch/mips/sgi/kernel/setup.c --- v2.3.99-pre8/linux/arch/mips/sgi/kernel/setup.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sgi/kernel/setup.c Sat May 13 08:29:14 2000 @@ -30,9 +30,10 @@ #ifdef CONFIG_REMOTE_DEBUG extern void rs_kgdb_hook(int); extern void breakpoint(void); +static int remote_debug = 0; #endif -#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) +#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SGI_PROM_CONSOLE) extern void console_setup(char *); #endif @@ -40,8 +41,6 @@ void indy_reboot_setup(void); void sgi_volume_set(unsigned char); -static int remote_debug = 0; - #define sgi_kh ((struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64)) #define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ @@ -166,7 +165,7 @@ * graphics console, it is set to "d" for the first serial * line and "d2" for the second serial line. */ - ctype = prom_getenv("console"); + ctype = ArcGetEnvironmentVariable("console"); if(*ctype == 'd') { if(*(ctype+1)=='2') console_setup ("ttyS1"); @@ -197,10 +196,10 @@ #endif #ifdef CONFIG_SGI_PROM_CONSOLE - console_setup("ttyS0", NULL); + console_setup("ttyS0"); #endif - - sgi_volume_set(simple_strtoul(prom_getenv("volume"), NULL, 10)); + + sgi_volume_set(simple_strtoul(ArcGetEnvironmentVariable("volume"), NULL, 10)); #ifdef CONFIG_VT #ifdef CONFIG_SGI_NEWPORT_CONSOLE @@ -231,3 +230,4 @@ init_vino(); #endif } +__initcall(rs_init); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/system.c linux/arch/mips/sgi/kernel/system.c --- v2.3.99-pre8/linux/arch/mips/sgi/kernel/system.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sgi/kernel/system.c Sat May 13 08:29:14 2000 @@ -3,7 +3,7 @@ * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * - * $Id: system.c,v 1.9 1999/10/21 00:23:05 ralf Exp $ + * $Id: system.c,v 1.8 1999/10/09 00:00:59 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/time.c linux/arch/mips/sgi/kernel/time.c --- v2.3.99-pre8/linux/arch/mips/sgi/kernel/time.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sgi/kernel/time.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.3 1999/10/09 00:00:59 ralf Exp $ +/* $Id: time.c,v 1.2 1998/04/05 11:24:00 ralf Exp $ * time.c: Generic SGI time_init() code, this will dispatch to the * appropriate per-architecture time/counter init code. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sni/Makefile linux/arch/mips/sni/Makefile --- v2.3.99-pre8/linux/arch/mips/sni/Makefile Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sni/Makefile Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.4 2000/02/18 00:24:30 ralf Exp $ +# $Id: Makefile,v 1.3 1999/01/04 16:03:57 ralf Exp $ # # Makefile for the SNI specific part of the kernel # diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sni/dma.c linux/arch/mips/sni/dma.c --- v2.3.99-pre8/linux/arch/mips/sni/dma.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sni/dma.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: dma.c,v 1.2 2000/02/24 00:12:41 ralf Exp $ +/* $Id: dma.c,v 1.1 2000/02/18 00:24:30 ralf Exp $ * * Dynamic DMA mapping support. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sni/int-handler.S linux/arch/mips/sni/int-handler.S --- v2.3.99-pre8/linux/arch/mips/sni/int-handler.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sni/int-handler.S Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: int-handler.S,v 1.5 1999/08/18 23:37:46 ralf Exp $ +/* $Id: int-handler.S,v 1.4 1999/01/04 16:03:58 ralf Exp $ * * SNI RM200 PCI specific interrupt handler code. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sni/io.c linux/arch/mips/sni/io.c --- v2.3.99-pre8/linux/arch/mips/sni/io.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sni/io.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: io.c,v 1.5 1999/10/09 00:00:59 ralf Exp $ +/* $Id: io.c,v 1.4 1999/08/18 23:37:46 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sni/pci.c linux/arch/mips/sni/pci.c --- v2.3.99-pre8/linux/arch/mips/sni/pci.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sni/pci.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: pci.c,v 1.10 2000/02/05 06:47:09 ralf Exp $ +/* $Id: pci.c,v 1.9 1999/12/04 03:59:00 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sni/pcimt_scache.c linux/arch/mips/sni/pcimt_scache.c --- v2.3.99-pre8/linux/arch/mips/sni/pcimt_scache.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sni/pcimt_scache.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: pcimt_scache.c,v 1.5 1999/10/09 00:00:59 ralf Exp $ +/* $Id: pcimt_scache.c,v 1.4 1999/01/04 16:03:59 ralf Exp $ * * arch/mips/sni/pcimt_scache.c * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sni/setup.c linux/arch/mips/sni/setup.c --- v2.3.99-pre8/linux/arch/mips/sni/setup.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/sni/setup.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.14 2000/01/27 01:05:23 ralf Exp $ +/* $Id: setup.c,v 1.13 1999/12/04 03:59:00 ralf Exp $ * * Setup pointers to hardware-dependent routines. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/tools/Makefile linux/arch/mips/tools/Makefile --- v2.3.99-pre8/linux/arch/mips/tools/Makefile Fri Jun 25 17:40:13 1999 +++ linux/arch/mips/tools/Makefile Sat May 13 08:29:14 2000 @@ -3,7 +3,7 @@ # Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) # Copyright (C) 1997 Ralf Baechle (ralf@gnu.ai.mit.edu) # -# $Id: Makefile,v 1.2 1997/12/01 17:57:41 ralf Exp $ +# $Id: Makefile,v 1.2 1997/09/23 06:23:49 ralf Exp $ # TARGET := $(TOPDIR)/include/asm-$(ARCH)/offset.h diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/tools/offset.c linux/arch/mips/tools/offset.c --- v2.3.99-pre8/linux/arch/mips/tools/offset.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips/tools/offset.c Sat May 13 08:29:14 2000 @@ -1,4 +1,4 @@ -/* $Id: offset.c,v 1.12 1999/10/09 00:00:59 ralf Exp $ +/* $Id: offset.c,v 1.11 1999/09/28 22:25:50 ralf Exp $ * * offset.c: Calculate pt_regs and task_struct offsets. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/Makefile linux/arch/mips64/Makefile --- v2.3.99-pre8/linux/arch/mips64/Makefile Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/Makefile Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.6 2000/01/29 01:41:59 ralf Exp $ +# $Id: Makefile,v 1.5 2000/01/21 22:34:03 ralf Exp $ # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/Makefile linux/arch/mips64/arc/Makefile --- v2.3.99-pre8/linux/arch/mips64/arc/Makefile Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/arc/Makefile Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.3 2000/01/17 23:32:46 ralf Exp $ +# $Id: Makefile,v 1.1 1999/08/20 21:13:32 ralf Exp $ # # Makefile for the ARC prom monitor library routines under Linux. # diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/cmdline.c linux/arch/mips64/arc/cmdline.c --- v2.3.99-pre8/linux/arch/mips64/arc/cmdline.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/arc/cmdline.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: cmdline.c,v 1.2 1999/11/19 23:29:05 ralf Exp $ +/* $Id: cmdline.c,v 1.2 1999/10/19 20:51:44 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/console.c linux/arch/mips64/arc/console.c --- v2.3.99-pre8/linux/arch/mips64/arc/console.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/arc/console.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: console.c,v 1.3 1999/11/19 23:29:05 ralf Exp $ +/* $Id: console.c,v 1.3 1999/10/19 20:51:44 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/env.c linux/arch/mips64/arc/env.c --- v2.3.99-pre8/linux/arch/mips64/arc/env.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/arc/env.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: env.c,v 1.4 1999/11/19 23:29:05 ralf Exp $ +/* $Id: env.c,v 1.4 1999/10/19 20:51:44 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/file.c linux/arch/mips64/arc/file.c --- v2.3.99-pre8/linux/arch/mips64/arc/file.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/arc/file.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: file.c,v 1.3 1999/11/19 23:29:05 ralf Exp $ +/* $Id: file.c,v 1.3 1999/10/19 20:51:44 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/identify.c linux/arch/mips64/arc/identify.c --- v2.3.99-pre8/linux/arch/mips64/arc/identify.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/arc/identify.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: identify.c,v 1.5 2000/01/17 23:32:46 ralf Exp $ +/* $Id: identify.c,v 1.5 1999/11/19 20:35:21 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/misc.c linux/arch/mips64/arc/misc.c --- v2.3.99-pre8/linux/arch/mips64/arc/misc.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/arc/misc.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.4 2000/01/17 23:32:46 ralf Exp $ +/* $Id: misc.c,v 1.2 1999/08/21 21:42:59 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/printf.c linux/arch/mips64/arc/printf.c --- v2.3.99-pre8/linux/arch/mips64/arc/printf.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/arc/printf.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: printf.c,v 1.2 1999/11/19 23:29:05 ralf Exp $ +/* $Id: printf.c,v 1.1 1999/08/20 21:13:33 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/salone.c linux/arch/mips64/arc/salone.c --- v2.3.99-pre8/linux/arch/mips64/arc/salone.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/arc/salone.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: salone.c,v 1.3 1999/11/19 23:29:05 ralf Exp $ +/* $Id: salone.c,v 1.2 1999/08/21 21:42:59 ralf Exp $ * * Routines to load into memory and execute stand-along program images using * ARCS PROM firmware. diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/time.c linux/arch/mips64/arc/time.c --- v2.3.99-pre8/linux/arch/mips64/arc/time.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/arc/time.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.3 1999/11/19 23:29:05 ralf Exp $ +/* $Id: time.c,v 1.2 1999/08/21 21:42:59 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/tree.c linux/arch/mips64/arc/tree.c --- v2.3.99-pre8/linux/arch/mips64/arc/tree.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/arc/tree.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: tree.c,v 1.4 1999/11/19 23:29:05 ralf Exp $ +/* $Id: tree.c,v 1.3 1999/09/27 16:01:37 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/boot/Makefile linux/arch/mips64/boot/Makefile --- v2.3.99-pre8/linux/arch/mips64/boot/Makefile Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/boot/Makefile Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.2 1999/12/04 03:59:00 ralf Exp $ +# $Id: Makefile,v 1.1 1999/08/18 21:46:52 ralf Exp $ # # This file is subject to the terms and conditions of the GNU General Public # License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/config.in linux/arch/mips64/config.in --- v2.3.99-pre8/linux/arch/mips64/config.in Tue Apr 11 15:09:13 2000 +++ linux/arch/mips64/config.in Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.14 2000/02/18 11:06:20 ulfc Exp $ +# $Id: config.in,v 1.19 2000/03/27 01:44:45 ralf Exp $ # # For a description of the syntax of this configuration file, # see the Configure script. @@ -17,26 +17,23 @@ if [ "$CONFIG_SGI_IP27" = "y" ]; then bool ' IP27 N-Mode' CONFIG_SGI_SN0_N_MODE bool ' Discontiguous Memory Support' CONFIG_DISCONTIGMEM + bool ' Multi-Processing support (Experimental)' CONFIG_SMP #bool ' IP27 XXL' CONFIG_SGI_SN0_XXL fi -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - bool 'Symmetric Multi-Processing support' CONFIG_SMP -fi endmenu # # Select some configuration options automatically based on user selections # -unset CONFIG_BOOT_ELF32 -unset CONFIG_BOOT_ELF64 unset CONFIG_ARC32 unset CONFIG_ARC64 +unset CONFIG_BINFMT_ELF32 unset CONFIG_BOARD_SCACHE +unset CONFIG_BOOT_ELF32 +unset CONFIG_BOOT_ELF64 unset CONFIG_COHERENT_IO -unset CONFIG_BINFMT_ELF32 - -define_bool CONFIG_ISA n -define_bool CONFIG_SBUS n +unset CONFIG_ISA +unset CONFIG_PCI if [ "$CONFIG_SGI_IP22" = "y" ]; then define_bool CONFIG_BOOT_ELF32 y @@ -51,10 +48,18 @@ define_bool CONFIG_COHERENT_IO y define_bool CONFIG_PCI y define_bool CONFIG_QL_ISP_A64 y -else +fi + +if [ "$CONFIG_ISA" != "y" ]; then + define_bool CONFIG_ISA n +fi + +if [ "$CONFIG_PCI" != "y" ]; then define_bool CONFIG_PCI n fi +define_bool CONFIG_SBUS n + mainmenu_option next_comment comment 'CPU selection' @@ -210,6 +215,8 @@ tristate 'SGI Newport Console support' CONFIG_SGI_NEWPORT_CONSOLE if [ "$CONFIG_SGI_NEWPORT_CONSOLE" != "y" ]; then define_bool CONFIG_DUMMY_CONSOLE y + else + define_bool CONFIG_FONT_8x16 y fi fi endmenu diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/defconfig linux/arch/mips64/defconfig --- v2.3.99-pre8/linux/arch/mips64/defconfig Thu May 11 15:30:06 2000 +++ linux/arch/mips64/defconfig Mon May 15 10:57:20 2000 @@ -14,13 +14,14 @@ CONFIG_SGI_IP27=y # CONFIG_SGI_SN0_N_MODE is not set # CONFIG_DISCONTIGMEM is not set -# CONFIG_ISA is not set -# CONFIG_SBUS is not set +# CONFIG_SMP is not set CONFIG_BOOT_ELF64=y CONFIG_ARC64=y CONFIG_COHERENT_IO=y CONFIG_PCI=y CONFIG_QL_ISP_A64=y +# CONFIG_ISA is not set +# CONFIG_SBUS is not set # # CPU selection @@ -43,7 +44,7 @@ # CONFIG_PCMCIA is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_SYSCTL is not set +CONFIG_SYSCTL=y CONFIG_BINFMT_ELF=y CONFIG_MIPS32_COMPAT=y CONFIG_BINFMT_ELF32=y @@ -52,7 +53,9 @@ # # Loadable module support # -# CONFIG_MODULES is not set +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y CONFIG_PCI_NAMES=y # @@ -69,8 +72,12 @@ # # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set # CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set # # Networking options @@ -149,12 +156,12 @@ # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_IPS is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA is not set # CONFIG_SCSI_EATA_DMA is not set @@ -180,11 +187,9 @@ CONFIG_SCSI_QLOGIC_ISP=y # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SEAGATE is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set # # I2O device support @@ -322,17 +327,13 @@ # CONFIG_DRM_TDFX is not set # -# USB support -# -# CONFIG_USB is not set - -# # File systems # # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set @@ -342,10 +343,12 @@ # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set @@ -353,23 +356,39 @@ # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types @@ -382,6 +401,7 @@ # CONFIG_MAC_PARTITION is not set # CONFIG_MSDOS_PARTITION is not set CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_NLS is not set CONFIG_KCORE_ELF=y @@ -392,8 +412,14 @@ # CONFIG_SOUND is not set # +# USB support +# +# CONFIG_USB is not set + +# # Kernel hacking # CONFIG_CROSSCOMPILE=y +# CONFIG_MIPS_FPE_MODULE is not set # CONFIG_REMOTE_DEBUG is not set -CONFIG_MAGIC_SYSRQ=y +# CONFIG_MAGIC_SYSRQ is not set diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/defconfig-ip22 linux/arch/mips64/defconfig-ip22 --- v2.3.99-pre8/linux/arch/mips64/defconfig-ip22 Thu May 11 15:30:06 2000 +++ linux/arch/mips64/defconfig-ip22 Mon May 15 10:57:20 2000 @@ -16,6 +16,9 @@ CONFIG_ARC32=y CONFIG_BOARD_SCACHE=y CONFIG_ARC_MEMORY=y +# CONFIG_ISA is not set +# CONFIG_PCI is not set +# CONFIG_SBUS is not set # # CPU selection @@ -32,14 +35,11 @@ # # CONFIG_CPU_LITTLE_ENDIAN is not set CONFIG_NET=y - -# -# PCMCIA/CardBus support -# +# CONFIG_HOTPLUG is not set # CONFIG_PCMCIA is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_SYSCTL is not set +CONFIG_SYSCTL=y CONFIG_BINFMT_ELF=y # CONFIG_MIPS32_COMPAT is not set # CONFIG_BINFMT_MISC is not set @@ -53,24 +53,22 @@ # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_IDE is not set - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_ONLY is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set # # Additional Block Devices # # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set # CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set +# CONFIG_BLK_DEV_INITRD is not set # # Networking options @@ -102,6 +100,7 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set +# CONFIG_DECNET is not set # # Telephony Support @@ -110,6 +109,13 @@ # CONFIG_PHONE_IXJ is not set # +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# # SCSI support # # CONFIG_SCSI is not set @@ -118,7 +124,6 @@ # I2O device support # # CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set # CONFIG_I2O_BLOCK is not set # CONFIG_I2O_LAN is not set # CONFIG_I2O_SCSI is not set @@ -134,6 +139,7 @@ # # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set +# CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_NET_SB1000 is not set @@ -158,7 +164,7 @@ # CONFIG_NET_RADIO is not set # -# Token Ring driver support +# Token Ring devices # # CONFIG_TR is not set # CONFIG_NET_FC is not set @@ -241,17 +247,13 @@ # CONFIG_DRM_TDFX is not set # -# USB support -# -# CONFIG_USB is not set - -# # File systems # # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set @@ -261,10 +263,12 @@ # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set @@ -272,23 +276,39 @@ # CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types @@ -301,6 +321,7 @@ # Console drivers # CONFIG_SGI_NEWPORT_CONSOLE=y +CONFIG_FONT_8x16=y CONFIG_KCORE_ELF=y # @@ -313,6 +334,11 @@ # # CONFIG_SGI_SERIAL is not set CONFIG_SGI_DS1286=y + +# +# USB support +# +# CONFIG_USB is not set # # Kernel hacking diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/defconfig-ip27 linux/arch/mips64/defconfig-ip27 --- v2.3.99-pre8/linux/arch/mips64/defconfig-ip27 Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/defconfig-ip27 Mon May 15 10:57:20 2000 @@ -14,11 +14,14 @@ CONFIG_SGI_IP27=y # CONFIG_SGI_SN0_N_MODE is not set # CONFIG_DISCONTIGMEM is not set +# CONFIG_SMP is not set CONFIG_BOOT_ELF64=y CONFIG_ARC64=y CONFIG_COHERENT_IO=y CONFIG_PCI=y CONFIG_QL_ISP_A64=y +# CONFIG_ISA is not set +# CONFIG_SBUS is not set # # CPU selection @@ -37,14 +40,11 @@ # CONFIG_CPU_LITTLE_ENDIAN is not set CONFIG_NET=y CONFIG_PCI_NAMES=y - -# -# PCMCIA/CardBus support -# +# CONFIG_HOTPLUG is not set # CONFIG_PCMCIA is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_SYSCTL is not set +CONFIG_SYSCTL=y CONFIG_BINFMT_ELF=y CONFIG_MIPS32_COMPAT=y CONFIG_BINFMT_ELF32=y @@ -53,33 +53,31 @@ # # Loadable module support # -# CONFIG_MODULES is not set +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y CONFIG_PCI_NAMES=y # # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_IDE is not set - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_ONLY is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set # # Additional Block Devices # # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set # CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set +# CONFIG_BLK_DEV_INITRD is not set # # Networking options @@ -111,6 +109,7 @@ # # CONFIG_IPX is not set # CONFIG_ATALK is not set +# CONFIG_DECNET is not set # # Telephony Support @@ -119,6 +118,13 @@ # CONFIG_PHONE_IXJ is not set # +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# # SCSI support # CONFIG_SCSI=y @@ -129,7 +135,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_SD_EXTRA_DEVS=40 # CONFIG_CHR_DEV_ST is not set -CONFIG_ST_EXTRA_DEVS=2 # CONFIG_BLK_DEV_SR is not set # CONFIG_CHR_DEV_SG is not set @@ -144,18 +149,19 @@ # # SCSI low-level drivers # +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set # CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_IPS is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA is not set # CONFIG_SCSI_EATA_DMA is not set @@ -181,11 +187,9 @@ CONFIG_SCSI_QLOGIC_ISP=y # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SEAGATE is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_ULTRASTOR is not set # # I2O device support @@ -207,6 +211,7 @@ # # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set +# CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_NET_SB1000 is not set @@ -221,7 +226,7 @@ # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set -# CONFIG_NET_EISA is not set +# CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set # @@ -240,7 +245,7 @@ # CONFIG_NET_RADIO is not set # -# Token Ring driver support +# Token Ring devices # # CONFIG_TR is not set # CONFIG_NET_FC is not set @@ -322,17 +327,13 @@ # CONFIG_DRM_TDFX is not set # -# USB support -# -# CONFIG_USB is not set - -# -# Filesystems +# File systems # # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set @@ -342,6 +343,7 @@ # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set @@ -349,6 +351,9 @@ # CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set # CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set # CONFIG_QNX4FS_RW is not set @@ -366,6 +371,7 @@ # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set # CONFIG_NFSD_V3 is not set @@ -373,12 +379,30 @@ CONFIG_LOCKD=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types # -# CONFIG_PARTITION_ADVANCED is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set # CONFIG_NLS is not set CONFIG_KCORE_ELF=y @@ -388,8 +412,14 @@ # CONFIG_SOUND is not set # +# USB support +# +# CONFIG_USB is not set + +# # Kernel hacking # CONFIG_CROSSCOMPILE=y +# CONFIG_MIPS_FPE_MODULE is not set # CONFIG_REMOTE_DEBUG is not set -CONFIG_MAGIC_SYSRQ=y +# CONFIG_MAGIC_SYSRQ is not set diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/Makefile linux/arch/mips64/kernel/Makefile --- v2.3.99-pre8/linux/arch/mips64/kernel/Makefile Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/Makefile Sat May 13 08:30:17 2000 @@ -18,11 +18,15 @@ OX_OBJS := mips64_ksyms.o ifdef CONFIG_MIPS32_COMPAT -O_OBJS += linux32.o scall_o32.o signal32.o +O_OBJS += linux32.o scall_o32.o signal32.o ioctl32.o endif ifdef CONFIG_BINFMT_ELF32 O_OBJS += binfmt_elf32.o +endif + +ifdef CONFIG_SMP +O_OBJS += smp.o endif clean: diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/binfmt_elf32.c linux/arch/mips64/kernel/binfmt_elf32.c --- v2.3.99-pre8/linux/arch/mips64/kernel/binfmt_elf32.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/binfmt_elf32.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: binfmt_elf32.c,v 1.2 2000/01/17 23:32:46 ralf Exp $ +/* $Id: binfmt_elf32.c,v 1.1 1999/11/24 06:56:13 ralf Exp $ * * Support for 32-bit Linux/MIPS ELF binaries. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/branch.c linux/arch/mips64/kernel/branch.c --- v2.3.99-pre8/linux/arch/mips64/kernel/branch.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/branch.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: branch.c,v 1.1 1999/12/04 03:59:00 ralf Exp $ +/* $Id: branch.c,v 1.1 1999/10/09 20:55:05 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/entry.S linux/arch/mips64/kernel/entry.S --- v2.3.99-pre8/linux/arch/mips64/kernel/entry.S Thu May 11 15:30:06 2000 +++ linux/arch/mips64/kernel/entry.S Sat May 13 08:30:17 2000 @@ -10,6 +10,7 @@ * Copyright (C) 1999, 2000 Silicon Graphics */ #include + #include #include #include @@ -34,10 +35,11 @@ FEXPORT(ret_from_sys_call) FEXPORT(ret_from_irq) -#ifdef CONFIG_SMP -#error Barffff... -#else la t1, softirq_state +#ifdef CONFIG_SMP + lwu t0, TASK_PROCESSOR($28) + dsll t0, t0, 5 + daddu t1, t0 #endif lw t0, 0 (t1) lw t1, 4 (t1) # unused delay slot diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/head.S linux/arch/mips64/kernel/head.S --- v2.3.99-pre8/linux/arch/mips64/kernel/head.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/head.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.4 2000/01/25 01:35:05 ralf Exp $ +/* $Id: head.S,v 1.6 2000/03/27 21:05:04 ulfc Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -20,6 +20,15 @@ #include #include +#define ARC64_TWIDDLE_PC \ +#ifdef CONFIG_ARC64 \ + /* We get launched at a XKPHYS address but the kernel is linked to \ + run at a KSEG0 address, so jump there. */ \ + la t0, 1f \ + jr t0 \ +1: \ +#endif + .text EXPORT(stext) # used for profiling @@ -29,13 +38,7 @@ NESTED(kernel_entry, 16, sp) # kernel entry point -#ifdef CONFIG_ARC64 - /* We get launched at a XKPHYS address but the kernel is linked to - run at a KSEG0 address, so jump there. */ - la t0, 1f - jr t0 -1: -#endif + ARC64_TWIDDLE_PC ori sp, 0xf # align stack on 16 byte. xori sp, 0xf @@ -47,24 +50,44 @@ CLI # disable interrupts mfc0 t0, CP0_STATUS - li t1, ~(ST0_CU1|ST0_CU2|ST0_CU3) + /* + * On IP27, I am seeing the TS bit set when the + * kernel is loaded. Maybe because the kernel is + * in ckseg0 and not xkphys? Clear it anyway ... + */ + li t1, ~(ST0_TS|ST0_CU1|ST0_CU2|ST0_CU3) and t0, t1 - or t0, (ST0_CU0|ST0_KX|ST0_SX) - mtc0 t0, CP0_STATUS + or t0, (ST0_CU0|ST0_KX|ST0_SX|ST0_FR) # Bogosity: cu0 indicates kernel + mtc0 t0, CP0_STATUS # thread in copy_thread. la $28, init_task_union # init current pointer daddiu t0, $28, KERNEL_STACK_SIZE-32 sd t0, kernelsp dsubu sp, t0, 4*SZREG # init stack pointer - + move t0, $28 +#ifdef CONFIG_SMP + mtc0 t0, CP0_WATCHLO + dsrl32 t0, t0, 0 + mtc0 t0, CP0_WATCHHI +#endif jal start_kernel 1: b 1b # just in case ... END(kernel_entry) +NESTED(bootstrap, 16, sp) + ARC64_TWIDDLE_PC + CLI + mfc0 t0, CP0_STATUS + li t1, ~(ST0_CU1|ST0_CU2|ST0_CU3) + and t0, t1 + or t0, (ST0_CU0|ST0_KX|ST0_SX|ST0_FR) # Bogosity: cu0 indicates kernel + mtc0 t0, CP0_STATUS # thread in copy_thread. + jal cboot + END(bootstrap) + __FINIT .comm kernelsp, 8, 8 # current stackpointer - .comm current_pgd, 8, 8 # current page tables #define PAGE_SIZE 0x1000 @@ -81,5 +104,5 @@ page swapper_pg_dir, 1 page invalid_pte_table, 1 page invalid_pmd_table, 1 + page empty_bad_page_table, 1 page empty_bad_page - page empty_bad_page_table diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/ioctl32.c linux/arch/mips64/kernel/ioctl32.c --- v2.3.99-pre8/linux/arch/mips64/kernel/ioctl32.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/kernel/ioctl32.c Sat May 13 08:30:17 2000 @@ -0,0 +1,529 @@ +/* $Id: ioctl32.c,v 1.1 2000/04/05 00:43:25 ulfc Exp $ + * ioctl32.c: Conversion between 32bit and 64bit native ioctls. + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Written by Ulf Carlsson (ulfc@engr.sgi.com) + * + * Mostly from the sparc64 ioctl32 implementation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define A(__x) ((unsigned long)(__x)) + +long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); + +struct timeval32 { + int tv_sec; + int tv_usec; +}; + +#define EXT2_IOC32_GETFLAGS _IOR('f', 1, int) +#define EXT2_IOC32_SETFLAGS _IOW('f', 2, int) +#define EXT2_IOC32_GETVERSION _IOR('v', 1, int) +#define EXT2_IOC32_SETVERSION _IOW('v', 2, int) + +static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct timeval32 *up = (struct timeval32 *)arg; + struct timeval ktv; + mm_segment_t old_fs = get_fs(); + int err; + + set_fs(KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&ktv); + set_fs(old_fs); + if(!err) { + err = put_user(ktv.tv_sec, &up->tv_sec); + err |= __put_user(ktv.tv_usec, &up->tv_usec); + } + return err; +} + +struct ifmap32 { + unsigned int mem_start; + unsigned int mem_end; + unsigned short base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; +}; + +struct ifreq32 { +#define IFHWADDRLEN 6 +#define IFNAMSIZ 16 + union { + char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + } ifr_ifrn; + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short ifru_flags; + int ifru_ivalue; + int ifru_mtu; + struct ifmap32 ifru_map; + char ifru_slave[IFNAMSIZ]; /* Just fits the size */ + char ifru_newname[IFNAMSIZ]; + __kernel_caddr_t32 ifru_data; + } ifr_ifru; +}; + +struct ifconf32 { + int ifc_len; /* size of buffer */ + __kernel_caddr_t32 ifcbuf; +}; + +static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct ireq32 *uir32 = (struct ireq32 *)arg; + struct net_device *dev; + struct ifreq32 ifr32; + + if (copy_from_user(&ifr32, uir32, sizeof(struct ifreq32))) + return -EFAULT; + + read_lock(&dev_base_lock); + dev = __dev_get_by_index(ifr32.ifr_ifindex); + if (!dev) { + read_unlock(&dev_base_lock); + return -ENODEV; + } + + strcpy(ifr32.ifr_name, dev->name); + read_unlock(&dev_base_lock); + + if (copy_to_user(uir32, &ifr32, sizeof(struct ifreq32))) + return -EFAULT; + + return 0; +} + +static inline int dev_ifconf(unsigned int fd, unsigned int cmd, + unsigned long arg) +{ + struct ioconf32 *uifc32 = (struct ioconf32 *)arg; + struct ifconf32 ifc32; + struct ifconf ifc; + struct ifreq32 *ifr32; + struct ifreq *ifr; + mm_segment_t old_fs; + int len; + int err; + + if (copy_from_user(&ifc32, uifc32, sizeof(struct ifconf32))) + return -EFAULT; + + if(ifc32.ifcbuf == 0) { + ifc32.ifc_len = 0; + ifc.ifc_len = 0; + ifc.ifc_buf = NULL; + } else { + ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32))) * + sizeof (struct ifreq); + ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL); + if (!ifc.ifc_buf) + return -ENOMEM; + } + ifr = ifc.ifc_req; + ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); + len = ifc32.ifc_len / sizeof (struct ifreq32); + while (len--) { + if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) { + err = -EFAULT; + goto out; + } + } + + old_fs = get_fs(); + set_fs (KERNEL_DS); + err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc); + set_fs (old_fs); + if (err) + goto out; + + ifr = ifc.ifc_req; + ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); + len = ifc.ifc_len / sizeof (struct ifreq); + ifc32.ifc_len = len * sizeof (struct ifreq32); + + while (len--) { + if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) { + err = -EFAULT; + goto out; + } + } + + if (copy_to_user(uifc32, &ifc32, sizeof(struct ifconf32))) { + err = -EFAULT; + goto out; + } +out: + if(ifc.ifc_buf != NULL) + kfree (ifc.ifc_buf); + return err; +} + +static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, + unsigned long arg) +{ + struct ifreq32 *uifr = (struct ifreq32 *)arg; + struct ifreq ifr; + mm_segment_t old_fs; + int err; + + switch (cmd) { + case SIOCSIFMAP: + err = copy_from_user(&ifr, uifr, sizeof(ifr.ifr_name)); + err |= __get_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start)); + err |= __get_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end)); + err |= __get_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr)); + err |= __get_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq)); + err |= __get_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma)); + err |= __get_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port)); + if (err) + return -EFAULT; + break; + default: + if (copy_from_user(&ifr, uifr, sizeof(struct ifreq32))) + return -EFAULT; + break; + } + old_fs = get_fs(); + set_fs (KERNEL_DS); + err = sys_ioctl (fd, cmd, (unsigned long)&ifr); + set_fs (old_fs); + if (!err) { + switch (cmd) { + case SIOCGIFFLAGS: + case SIOCGIFMETRIC: + case SIOCGIFMTU: + case SIOCGIFMEM: + case SIOCGIFHWADDR: + case SIOCGIFINDEX: + case SIOCGIFADDR: + case SIOCGIFBRDADDR: + case SIOCGIFDSTADDR: + case SIOCGIFNETMASK: + case SIOCGIFTXQLEN: + if (copy_to_user(uifr, &ifr, sizeof(struct ifreq32))) + return -EFAULT; + break; + case SIOCGIFMAP: + err = copy_to_user(uifr, &ifr, sizeof(ifr.ifr_name)); + err |= __put_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start)); + err |= __put_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end)); + err |= __put_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr)); + err |= __put_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq)); + err |= __put_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma)); + err |= __put_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port)); + if (err) + err = -EFAULT; + break; + } + } + return err; +} + +struct rtentry32 +{ + unsigned int rt_pad1; + struct sockaddr rt_dst; /* target address */ + struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ + struct sockaddr rt_genmask; /* target network mask (IP) */ + unsigned short rt_flags; + short rt_pad2; + unsigned int rt_pad3; + unsigned int rt_pad4; + short rt_metric; /* +1 for binary compatibility! */ + unsigned int rt_dev; /* forcing the device at add */ + unsigned int rt_mtu; /* per route MTU/Window */ +#ifndef __KERNEL__ +#define rt_mss rt_mtu /* Compatibility :-( */ +#endif + unsigned int rt_window; /* Window clamping */ + unsigned short rt_irtt; /* Initial RTT */ +}; + +static inline int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct rtentry32 *ur = (struct rtentry32 *)arg; + struct rtentry r; + char devname[16]; + u32 rtdev; + int ret; + mm_segment_t old_fs = get_fs(); + + ret = copy_from_user (&r.rt_dst, &(ur->rt_dst), 3 * sizeof(struct sockaddr)); + ret |= __get_user (r.rt_flags, &(ur->rt_flags)); + ret |= __get_user (r.rt_metric, &(ur->rt_metric)); + ret |= __get_user (r.rt_mtu, &(ur->rt_mtu)); + ret |= __get_user (r.rt_window, &(ur->rt_window)); + ret |= __get_user (r.rt_irtt, &(ur->rt_irtt)); + ret |= __get_user (rtdev, &(ur->rt_dev)); + if (rtdev) { + ret |= copy_from_user (devname, (char *)A(rtdev), 15); + r.rt_dev = devname; devname[15] = 0; + } else + r.rt_dev = 0; + if (ret) + return -EFAULT; + set_fs (KERNEL_DS); + ret = sys_ioctl (fd, cmd, (long)&r); + set_fs (old_fs); + return ret; +} + +static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + /* These are just misnamed, they actually get/put from/to user an int */ + switch (cmd) { + case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break; + case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break; + case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break; + case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break; + } + return sys_ioctl(fd, cmd, arg); +} + +static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + int err; + unsigned long val; + + set_fs (KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&val); + set_fs (old_fs); + if (!err && put_user((unsigned int) val, (u32 *)arg)) + return -EFAULT; + return err; +} + +struct ioctl32_handler { + unsigned int cmd; + int (*function)(unsigned int, unsigned int, unsigned long); +}; + +struct ioctl32_list { + struct ioctl32_handler handler; + struct ioctl32_list *next; +}; + +#define IOCTL32_DEFAULT(cmd) { { cmd, (void *) sys_ioctl }, 0 } +#define IOCTL32_HANDLER(cmd, handler) { { cmd, (void *) handler }, 0 } + +static struct ioctl32_list ioctl32_handler_table[] = { + IOCTL32_DEFAULT(TCGETA), + IOCTL32_DEFAULT(TCSETA), + IOCTL32_DEFAULT(TCSETAW), + IOCTL32_DEFAULT(TCSETAF), + IOCTL32_DEFAULT(TCSBRK), + IOCTL32_DEFAULT(TCXONC), + IOCTL32_DEFAULT(TCFLSH), + IOCTL32_DEFAULT(TCGETS), + IOCTL32_DEFAULT(TCSETS), + IOCTL32_DEFAULT(TCSETSW), + IOCTL32_DEFAULT(TCSETSF), + IOCTL32_DEFAULT(TIOCLINUX), + + IOCTL32_DEFAULT(TIOCGETD), + IOCTL32_DEFAULT(TIOCSETD), + IOCTL32_DEFAULT(TIOCEXCL), + IOCTL32_DEFAULT(TIOCNXCL), + IOCTL32_DEFAULT(TIOCCONS), + IOCTL32_DEFAULT(TIOCGSOFTCAR), + IOCTL32_DEFAULT(TIOCSSOFTCAR), + IOCTL32_DEFAULT(TIOCSWINSZ), + IOCTL32_DEFAULT(TIOCGWINSZ), + IOCTL32_DEFAULT(TIOCMGET), + IOCTL32_DEFAULT(TIOCMBIC), + IOCTL32_DEFAULT(TIOCMBIS), + IOCTL32_DEFAULT(TIOCMSET), + IOCTL32_DEFAULT(TIOCPKT), + IOCTL32_DEFAULT(TIOCNOTTY), + IOCTL32_DEFAULT(TIOCSTI), + IOCTL32_DEFAULT(TIOCOUTQ), + IOCTL32_DEFAULT(TIOCSPGRP), + IOCTL32_DEFAULT(TIOCGPGRP), + IOCTL32_DEFAULT(TIOCSCTTY), + IOCTL32_DEFAULT(TIOCGPTN), + IOCTL32_DEFAULT(TIOCSPTLCK), + IOCTL32_DEFAULT(TIOCGSERIAL), + IOCTL32_DEFAULT(TIOCSSERIAL), + IOCTL32_DEFAULT(TIOCSERGETLSR), + + IOCTL32_DEFAULT(FIOCLEX), + IOCTL32_DEFAULT(FIONCLEX), + IOCTL32_DEFAULT(FIOASYNC), + IOCTL32_DEFAULT(FIONBIO), + IOCTL32_DEFAULT(FIONREAD), + + IOCTL32_DEFAULT(PIO_FONT), + IOCTL32_DEFAULT(GIO_FONT), + IOCTL32_DEFAULT(KDSIGACCEPT), + IOCTL32_DEFAULT(KDGETKEYCODE), + IOCTL32_DEFAULT(KDSETKEYCODE), + IOCTL32_DEFAULT(KIOCSOUND), + IOCTL32_DEFAULT(KDMKTONE), + IOCTL32_DEFAULT(KDGKBTYPE), + IOCTL32_DEFAULT(KDSETMODE), + IOCTL32_DEFAULT(KDGETMODE), + IOCTL32_DEFAULT(KDSKBMODE), + IOCTL32_DEFAULT(KDGKBMODE), + IOCTL32_DEFAULT(KDSKBMETA), + IOCTL32_DEFAULT(KDGKBMETA), + IOCTL32_DEFAULT(KDGKBENT), + IOCTL32_DEFAULT(KDSKBENT), + IOCTL32_DEFAULT(KDGKBSENT), + IOCTL32_DEFAULT(KDSKBSENT), + IOCTL32_DEFAULT(KDGKBDIACR), + IOCTL32_DEFAULT(KDSKBDIACR), + IOCTL32_DEFAULT(KDGKBLED), + IOCTL32_DEFAULT(KDSKBLED), + IOCTL32_DEFAULT(KDGETLED), + IOCTL32_DEFAULT(KDSETLED), + IOCTL32_DEFAULT(GIO_SCRNMAP), + IOCTL32_DEFAULT(PIO_SCRNMAP), + IOCTL32_DEFAULT(GIO_UNISCRNMAP), + IOCTL32_DEFAULT(PIO_UNISCRNMAP), + IOCTL32_DEFAULT(PIO_FONTRESET), + IOCTL32_DEFAULT(PIO_UNIMAPCLR), + + IOCTL32_DEFAULT(VT_SETMODE), + IOCTL32_DEFAULT(VT_GETMODE), + IOCTL32_DEFAULT(VT_GETSTATE), + IOCTL32_DEFAULT(VT_OPENQRY), + IOCTL32_DEFAULT(VT_ACTIVATE), + IOCTL32_DEFAULT(VT_WAITACTIVE), + IOCTL32_DEFAULT(VT_RELDISP), + IOCTL32_DEFAULT(VT_DISALLOCATE), + IOCTL32_DEFAULT(VT_RESIZE), + IOCTL32_DEFAULT(VT_RESIZEX), + IOCTL32_DEFAULT(VT_LOCKSWITCH), + IOCTL32_DEFAULT(VT_UNLOCKSWITCH), + + IOCTL32_HANDLER(SIOCGIFNAME, dev_ifname32), + IOCTL32_HANDLER(SIOCGIFCONF, dev_ifconf), + IOCTL32_HANDLER(SIOCGIFFLAGS, dev_ifsioc), + IOCTL32_HANDLER(SIOCSIFFLAGS, dev_ifsioc), + IOCTL32_HANDLER(SIOCGIFMETRIC, dev_ifsioc), + IOCTL32_HANDLER(SIOCSIFMETRIC, dev_ifsioc), + IOCTL32_HANDLER(SIOCGIFMTU, dev_ifsioc), + IOCTL32_HANDLER(SIOCSIFMTU, dev_ifsioc), + IOCTL32_HANDLER(SIOCGIFMEM, dev_ifsioc), + IOCTL32_HANDLER(SIOCSIFMEM, dev_ifsioc), + IOCTL32_HANDLER(SIOCGIFHWADDR, dev_ifsioc), + IOCTL32_HANDLER(SIOCSIFHWADDR, dev_ifsioc), + IOCTL32_HANDLER(SIOCADDMULTI, dev_ifsioc), + IOCTL32_HANDLER(SIOCDELMULTI, dev_ifsioc), + IOCTL32_HANDLER(SIOCGIFINDEX, dev_ifsioc), + IOCTL32_HANDLER(SIOCGIFMAP, dev_ifsioc), + IOCTL32_HANDLER(SIOCSIFMAP, dev_ifsioc), + IOCTL32_HANDLER(SIOCGIFADDR, dev_ifsioc), + IOCTL32_HANDLER(SIOCSIFADDR, dev_ifsioc), + IOCTL32_HANDLER(SIOCGIFBRDADDR, dev_ifsioc), + IOCTL32_HANDLER(SIOCSIFBRDADDR, dev_ifsioc), + IOCTL32_HANDLER(SIOCGIFDSTADDR, dev_ifsioc), + IOCTL32_HANDLER(SIOCSIFDSTADDR, dev_ifsioc), + IOCTL32_HANDLER(SIOCGIFNETMASK, dev_ifsioc), + IOCTL32_HANDLER(SIOCSIFNETMASK, dev_ifsioc), + IOCTL32_HANDLER(SIOCSIFPFLAGS, dev_ifsioc), + IOCTL32_HANDLER(SIOCGIFPFLAGS, dev_ifsioc), + IOCTL32_HANDLER(SIOCGIFTXQLEN, dev_ifsioc), + IOCTL32_HANDLER(SIOCSIFTXQLEN, dev_ifsioc), + IOCTL32_HANDLER(SIOCADDRT, routing_ioctl), + IOCTL32_HANDLER(SIOCDELRT, routing_ioctl), + + IOCTL32_HANDLER(EXT2_IOC32_GETFLAGS, do_ext2_ioctl), + IOCTL32_HANDLER(EXT2_IOC32_SETFLAGS, do_ext2_ioctl), + IOCTL32_HANDLER(EXT2_IOC32_GETVERSION, do_ext2_ioctl), + IOCTL32_HANDLER(EXT2_IOC32_SETVERSION, do_ext2_ioctl), + + IOCTL32_HANDLER(BLKGETSIZE, w_long) + +}; + +#define NR_IOCTL32_HANDLERS (sizeof(ioctl32_handler_table) / \ + sizeof(ioctl32_handler_table[0])) + +static struct ioctl32_list *ioctl32_hash_table[1024]; + +static inline int ioctl32_hash(unsigned int cmd) +{ + return ((cmd >> 6) ^ (cmd >> 4) ^ cmd) & 0x3ff; +} + +int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned int arg) +{ + int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp); + struct file *filp; + struct ioctl32_list *l; + int error; + + l = ioctl32_hash_table[ioctl32_hash(cmd)]; + + error = -EBADF; + + filp = fget(fd); + if (!filp) + return error; + + if (!filp->f_op || !filp->f_op->ioctl) { + error = sys_ioctl (fd, cmd, arg); + goto out; + } + + while (l && l->handler.cmd != cmd) + l = l->next; + + if (l) { + handler = (void *)l->handler.function; + error = handler(fd, cmd, arg, filp); + } else { + error = -EINVAL; + printk("unknown ioctl: %08x\n", cmd); + } +out: + fput(filp); + return error; +} + +static void ioctl32_insert(struct ioctl32_list *entry) +{ + int hash = ioctl32_hash(entry->handler.cmd); + if (!ioctl32_hash_table[hash]) + ioctl32_hash_table[hash] = entry; + else { + struct ioctl32_list *l; + l = ioctl32_hash_table[hash]; + while (l->next) + l = l->next; + l->next = entry; + entry->next = 0; + } +} + +static int __init init_ioctl32(void) +{ + int i; + for (i = 0; i < NR_IOCTL32_HANDLERS; i++) + ioctl32_insert(&ioctl32_handler_table[i]); + return 0; +} + +__initcall(init_ioctl32); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/linux32.c linux/arch/mips64/kernel/linux32.c --- v2.3.99-pre8/linux/arch/mips64/kernel/linux32.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/linux32.c Sat May 13 08:30:17 2000 @@ -1,10 +1,1309 @@ -int sys32_newstat(void) {return 0;} -int sys32_newlstat(void) {return 0;} -int sys32_newfstat(void) {return 0;} -int sys_mmap2(void) {return 0;} -int sys_truncate64(void) {return 0;} -int sys_ftruncate64(void) {return 0;} -int sys_stat64(void) {return 0;} -int sys_lstat64(void) {return 0;} -int sys_fstat64(void) {return 0;} +/* $Id: linux32.c,v 1.14 2000/03/23 00:30:53 ulfc Exp $ + * + * Conversion between 32-bit and 64-bit native system calls. + * + * Copyright (C) 2000 Silicon Graphics, Inc. + * Written by Ulf Carlsson (ulfc@engr.sgi.com) + * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com) + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +#define A(__x) ((unsigned long)(__x)) + +#if 1 +static inline int +putstat(struct stat32 *ubuf, struct stat *kbuf) +{ + int err; + + err = put_user (kbuf->st_dev, &ubuf->st_dev); + err |= __put_user (kbuf->st_ino, &ubuf->st_ino); + err |= __put_user (kbuf->st_mode, &ubuf->st_mode); + err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink); + err |= __put_user (kbuf->st_uid, &ubuf->st_uid); + err |= __put_user (kbuf->st_gid, &ubuf->st_gid); + err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev); + err |= __put_user (kbuf->st_size, &ubuf->st_size); + err |= __put_user (kbuf->st_atime, &ubuf->st_atime); + err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime); + err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime); + err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize); + err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks); + return err; +} + +extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf); + +asmlinkage int +sys32_newstat(char * filename, struct stat32 *statbuf) +{ + int ret; + struct stat s; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_newstat(filename, &s); + set_fs (old_fs); + if (putstat (statbuf, &s)) + return -EFAULT; + return ret; +} + +extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf); + +asmlinkage int +sys32_newlstat(char * filename, struct stat32 *statbuf) +{ + int ret; + struct stat s; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_newlstat(filename, &s); + set_fs (old_fs); + if (putstat (statbuf, &s)) + return -EFAULT; + return ret; +} + +extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf); + +asmlinkage int +sys32_newfstat(unsigned int fd, struct stat32 *statbuf) +{ + int ret; + struct stat s; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_newfstat(fd, &s); + set_fs (old_fs); + if (putstat (statbuf, &s)) + return -EFAULT; + return ret; +} +#else +/* + * Revalidate the inode. This is required for proper NFS attribute caching. + */ +static __inline__ int +do_revalidate(struct dentry *dentry) +{ + struct inode * inode = dentry->d_inode; + if (inode->i_op && inode->i_op->revalidate) + return inode->i_op->revalidate(dentry); + return 0; +} + +static int cp_new_stat32(struct inode * inode, struct stat32 * statbuf) +{ + struct stat32 tmp; + unsigned int blocks, indirect; + + memset(&tmp, 0, sizeof(tmp)); + tmp.st_dev = kdev_t_to_nr(inode->i_dev); + tmp.st_ino = inode->i_ino; + tmp.st_mode = inode->i_mode; + tmp.st_nlink = inode->i_nlink; + SET_STAT_UID(tmp, inode->i_uid); + SET_STAT_GID(tmp, inode->i_gid); + tmp.st_rdev = kdev_t_to_nr(inode->i_rdev); + tmp.st_size = inode->i_size; + tmp.st_atime = inode->i_atime; + tmp.st_mtime = inode->i_mtime; + tmp.st_ctime = inode->i_ctime; +/* + * st_blocks and st_blksize are approximated with a simple algorithm if + * they aren't supported directly by the filesystem. The minix and msdos + * filesystems don't keep track of blocks, so they would either have to + * be counted explicitly (by delving into the file itself), or by using + * this simple algorithm to get a reasonable (although not 100% accurate) + * value. + */ + +/* + * Use minix fs values for the number of direct and indirect blocks. The + * count is now exact for the minix fs except that it counts zero blocks. + * Everything is in units of BLOCK_SIZE until the assignment to + * tmp.st_blksize. + */ +#define D_B 7 +#define I_B (BLOCK_SIZE / sizeof(unsigned short)) + + if (!inode->i_blksize) { + blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (blocks > D_B) { + indirect = (blocks - D_B + I_B - 1) / I_B; + blocks += indirect; + if (indirect > 1) { + indirect = (indirect - 1 + I_B - 1) / I_B; + blocks += indirect; + if (indirect > 1) + blocks++; + } + } + tmp.st_blocks = (BLOCK_SIZE / 512) * blocks; + tmp.st_blksize = BLOCK_SIZE; + } else { + tmp.st_blocks = inode->i_blocks; + tmp.st_blksize = inode->i_blksize; + } + return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; +} +asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf) +{ + struct dentry * dentry; + int error; + + lock_kernel(); + dentry = namei(filename); + + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + error = do_revalidate(dentry); + if (!error) + error = cp_new_stat32(dentry->d_inode, statbuf); + + dput(dentry); + } + unlock_kernel(); + return error; +} +asmlinkage int sys32_newlstat(char *filename, struct stat32 * statbuf) +{ + struct dentry * dentry; + int error; + + lock_kernel(); + dentry = lnamei(filename); + + error = PTR_ERR(dentry); + if (!IS_ERR(dentry)) { + error = do_revalidate(dentry); + if (!error) + error = cp_new_stat32(dentry->d_inode, statbuf); + + dput(dentry); + } + unlock_kernel(); + return error; +} + +asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 * statbuf) +{ + struct file * f; + int err = -EBADF; + + lock_kernel(); + f = fget(fd); + if (f) { + struct dentry * dentry = f->f_dentry; + + err = do_revalidate(dentry); + if (!err) + err = cp_new_stat32(dentry->d_inode, statbuf); + fput(f); + } + unlock_kernel(); + return err; +} +#endif +asmlinkage int sys_mmap2(void) {return 0;} + +asmlinkage long sys_truncate(const char * path, unsigned long length); + +asmlinkage int sys_truncate64(const char *path, unsigned int high, + unsigned int low) +{ + if ((int)high < 0) + return -EINVAL; + return sys_truncate(path, (high << 32) | low); +} + +asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); + +asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high, + unsigned int low) +{ + if ((int)high < 0) + return -EINVAL; + return sys_ftruncate(fd, (high << 32) | low); +} + +asmlinkage long sys_newstat(char * filename, struct stat * statbuf); + +asmlinkage int sys_stat64(char * filename, struct stat *statbuf) +{ + return sys_newstat(filename, statbuf); +} + +asmlinkage long sys_newlstat(char * filename, struct stat * statbuf); + +asmlinkage int sys_lstat64(char * filename, struct stat *statbuf) +{ + return sys_newlstat(filename, statbuf); +} + +asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf); + +asmlinkage int sys_fstat64(unsigned int fd, struct stat *statbuf) +{ + return sys_newfstat(fd, statbuf); +} + +#if 0 +/* + * count32() counts the number of arguments/envelopes + */ +static int count32(u32 * argv, int max) +{ + int i = 0; + + if (argv != NULL) { + for (;;) { + u32 p; + /* egcs is stupid */ + if (!access_ok(VERIFY_READ, argv, sizeof (u32))) + return -EFAULT; + __get_user(p,argv); + if (!p) + break; + argv++; + if(++i > max) + return -E2BIG; + } + } + return i; +} + + +/* + * 'copy_strings32()' copies argument/envelope strings from user + * memory to free pages in kernel mem. These are in a format ready + * to be put directly into the top of new user memory. + */ +int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm) +{ + while (argc-- > 0) { + u32 str; + int len; + unsigned long pos; + + if (get_user(str, argv+argc) || !str || !(len = strnlen_user((char *)A(str), bprm->p))) + return -EFAULT; + if (bprm->p < len) + return -E2BIG; + + bprm->p -= len; + /* XXX: add architecture specific overflow check here. */ + + pos = bprm->p; + while (len > 0) { + char *kaddr; + int i, new, err; + struct page *page; + int offset, bytes_to_copy; + + offset = pos % PAGE_SIZE; + i = pos/PAGE_SIZE; + page = bprm->page[i]; + new = 0; + if (!page) { + page = alloc_page(GFP_HIGHUSER); + bprm->page[i] = page; + if (!page) + return -ENOMEM; + new = 1; + } + kaddr = (char *)kmap(page); + + if (new && offset) + memset(kaddr, 0, offset); + bytes_to_copy = PAGE_SIZE - offset; + if (bytes_to_copy > len) { + bytes_to_copy = len; + if (new) + memset(kaddr+offset+len, 0, PAGE_SIZE-offset-len); + } + err = copy_from_user(kaddr + offset, (char *)A(str), bytes_to_copy); + flush_page_to_ram(page); + kunmap(page); + + if (err) + return -EFAULT; + + pos += bytes_to_copy; + str += bytes_to_copy; + len -= bytes_to_copy; + } + } + return 0; +} + + +/* + * sys_execve32() executes a new program. + */ +int do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) +{ + struct linux_binprm bprm; + struct dentry * dentry; + int retval; + int i; + + bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); + memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); + + dentry = open_namei(filename, 0, 0); + retval = PTR_ERR(dentry); + if (IS_ERR(dentry)) + return retval; + + bprm.dentry = dentry; + bprm.filename = filename; + bprm.sh_bang = 0; + bprm.loader = 0; + bprm.exec = 0; + if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) { + dput(dentry); + return bprm.argc; + } + + if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) { + dput(dentry); + return bprm.envc; + } + + retval = prepare_binprm(&bprm); + if (retval < 0) + goto out; + + retval = copy_strings_kernel(1, &bprm.filename, &bprm); + if (retval < 0) + goto out; + + bprm.exec = bprm.p; + retval = copy_strings32(bprm.envc, envp, &bprm); + if (retval < 0) + goto out; + + retval = copy_strings32(bprm.argc, argv, &bprm); + if (retval < 0) + goto out; + + retval = search_binary_handler(&bprm,regs); + if (retval >= 0) + /* execve success */ + return retval; + +out: + /* Something went wrong, return the inode and free the argument pages*/ + if (bprm.dentry) + dput(bprm.dentry); + + /* Assumes that free_page() can take a NULL argument. */ + /* I hope this is ok for all architectures */ + for (i = 0 ; i < MAX_ARG_PAGES ; i++) + if (bprm.page[i]) + __free_page(bprm.page[i]); + + return retval; +} + +/* + * sys_execve() executes a new program. + */ +asmlinkage int sys32_execve(abi64_no_regargs, struct pt_regs regs) +{ + int error; + char * filename; + + filename = getname((char *) (long)regs.regs[4]); + printk("Executing: %s\n", filename); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = do_execve32(filename, (u32 *) (long)regs.regs[5], + (u32 *) (long)regs.regs[6], ®s); + putname(filename); + +out: + return error; +} +#else +static int +nargs(unsigned int arg, char **ap) +{ + char *ptr; + int n; + + n = 0; + do { + /* egcs is stupid */ + if (!access_ok(VERIFY_READ, arg, sizeof (unsigned int))) + return -EFAULT; + __get_user((long)ptr,(int *)A(arg)); + if (ap) + *ap++ = ptr; + arg += sizeof(unsigned int); + n++; + } while (ptr); + return(n - 1); +} + +asmlinkage int +sys32_execve(abi64_no_regargs, struct pt_regs regs) +{ + extern asmlinkage int sys_execve(abi64_no_regargs, struct pt_regs regs); + extern asmlinkage long sys_munmap(unsigned long addr, size_t len); + unsigned int argv = (unsigned int)regs.regs[5]; + unsigned int envp = (unsigned int)regs.regs[6]; + char **av, **ae; + int na, ne, r, len; + char * filename; + + na = nargs(argv, NULL); + ne = nargs(envp, NULL); + len = (na + ne + 2) * sizeof(*av); + /* + * kmalloc won't work because the `sys_exec' code will attempt + * to do a `get_user' on the arg list and `get_user' will fail + * on a kernel address (simplifies `get_user'). Instead we + * do an mmap to get a user address. Note that since a successful + * `execve' frees all current memory we only have to do an + * `munmap' if the `execve' failes. + */ + down(¤t->mm->mmap_sem); + lock_kernel(); + + av = (char **) do_mmap_pgoff(0, 0, len, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0); + + unlock_kernel(); + up(¤t->mm->mmap_sem); + + if (IS_ERR(av)) + return((long) av); + ae = av + na + 1; + av[na] = (char *)0; + ae[ne] = (char *)0; + (void)nargs(argv, av); + (void)nargs(envp, ae); + filename = getname((char *) (long)regs.regs[4]); + r = PTR_ERR(filename); + if (IS_ERR(filename)) + return(r); + + r = do_execve(filename, av, ae, ®s); + putname(filename); + if (IS_ERR(r)) + sys_munmap((unsigned long)av, len); + return(r); +} +#endif + +struct dirent32 { + unsigned int d_ino; + unsigned int d_off; + unsigned short d_reclen; + char d_name[NAME_MAX + 1]; +}; + +static void +xlate_dirent(void *dirent64, void *dirent32, long n) +{ + long off; + struct dirent *dirp; + struct dirent32 *dirp32; + + off = 0; + while (off < n) { + dirp = (struct dirent *)(dirent64 + off); + dirp32 = (struct dirent32 *)(dirent32 + off); + off += dirp->d_reclen; + dirp32->d_ino = dirp->d_ino; + dirp32->d_off = (unsigned int)dirp->d_off; + dirp32->d_reclen = dirp->d_reclen; + strncpy(dirp32->d_name, dirp->d_name, dirp->d_reclen - ((3 * 4) + 2)); + } + return; +} + +asmlinkage long sys_getdents(unsigned int fd, void * dirent, unsigned int count); + +asmlinkage long +sys32_getdents(unsigned int fd, void * dirent32, unsigned int count) +{ + long n; + void *dirent64; + + dirent64 = (void *)((unsigned long)(dirent32 + (sizeof(long) - 1)) & ~(sizeof(long) - 1)); + if ((n = sys_getdents(fd, dirent64, count - (dirent64 - dirent32))) < 0) + return(n); + xlate_dirent(dirent64, dirent32, n); + return(n); +} + +asmlinkage int old_readdir(unsigned int fd, void * dirent, unsigned int count); + +asmlinkage int +sys32_readdir(unsigned int fd, void * dirent32, unsigned int count) +{ + int n; + struct dirent dirent64; + + if ((n = old_readdir(fd, &dirent64, count)) < 0) + return(n); + xlate_dirent(&dirent64, dirent32, dirent64.d_reclen); + return(n); +} + +struct timeval32 +{ + int tv_sec, tv_usec; +}; + +struct itimerval32 +{ + struct timeval32 it_interval; + struct timeval32 it_value; +}; + +struct rusage32 { + struct timeval32 ru_utime; + struct timeval32 ru_stime; + int ru_maxrss; + int ru_ixrss; + int ru_idrss; + int ru_isrss; + int ru_minflt; + int ru_majflt; + int ru_nswap; + int ru_inblock; + int ru_oublock; + int ru_msgsnd; + int ru_msgrcv; + int ru_nsignals; + int ru_nvcsw; + int ru_nivcsw; +}; + +static int +put_rusage (struct rusage32 *ru, struct rusage *r) +{ + int err; + + err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); + err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec); + err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec); + err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec); + err |= __put_user (r->ru_maxrss, &ru->ru_maxrss); + err |= __put_user (r->ru_ixrss, &ru->ru_ixrss); + err |= __put_user (r->ru_idrss, &ru->ru_idrss); + err |= __put_user (r->ru_isrss, &ru->ru_isrss); + err |= __put_user (r->ru_minflt, &ru->ru_minflt); + err |= __put_user (r->ru_majflt, &ru->ru_majflt); + err |= __put_user (r->ru_nswap, &ru->ru_nswap); + err |= __put_user (r->ru_inblock, &ru->ru_inblock); + err |= __put_user (r->ru_oublock, &ru->ru_oublock); + err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd); + err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv); + err |= __put_user (r->ru_nsignals, &ru->ru_nsignals); + err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw); + err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw); + return err; +} + +extern asmlinkage int sys_wait4(pid_t pid, unsigned int * stat_addr, + int options, struct rusage * ru); + +asmlinkage int +sys32_wait4(__kernel_pid_t32 pid, unsigned int * stat_addr, int options, + struct rusage32 * ru) +{ + if (!ru) + return sys_wait4(pid, stat_addr, options, NULL); + else { + struct rusage r; + int ret; + unsigned int status; + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); + set_fs(old_fs); + if (put_rusage (ru, &r)) return -EFAULT; + if (stat_addr && put_user (status, stat_addr)) + return -EFAULT; + return ret; + } +} + +asmlinkage int +sys32_waitpid(__kernel_pid_t32 pid, unsigned int *stat_addr, int options) +{ + return sys32_wait4(pid, stat_addr, options, NULL); +} + +#define RLIM_INFINITY32 0x7fffffff +#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) + +struct rlimit32 { + int rlim_cur; + int rlim_max; +}; + +extern asmlinkage int sys_old_getrlimit(unsigned int resource, struct rlimit *rlim); + +asmlinkage int +sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim) +{ + struct rlimit r; + int ret; + mm_segment_t old_fs = get_fs (); + + set_fs (KERNEL_DS); + ret = sys_old_getrlimit(resource, &r); + set_fs (old_fs); + if (!ret) { + ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur); + ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max); + } + return ret; +} + +extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim); + +asmlinkage int +sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim) +{ + struct rlimit r; + int ret; + mm_segment_t old_fs = get_fs (); + + if (resource >= RLIM_NLIMITS) return -EINVAL; + if (get_user (r.rlim_cur, &rlim->rlim_cur) || + __get_user (r.rlim_max, &rlim->rlim_max)) + return -EFAULT; + if (r.rlim_cur == RLIM_INFINITY32) + r.rlim_cur = RLIM_INFINITY; + if (r.rlim_max == RLIM_INFINITY32) + r.rlim_max = RLIM_INFINITY; + set_fs (KERNEL_DS); + ret = sys_setrlimit(resource, &r); + set_fs (old_fs); + return ret; +} + +struct statfs32 { + int f_type; + int f_bsize; + int f_frsize; + int f_blocks; + int f_bfree; + int f_files; + int f_ffree; + int f_bavail; + __kernel_fsid_t32 f_fsid; + int f_namelen; + int f_spare[6]; +}; + +static inline int +put_statfs (struct statfs32 *ubuf, struct statfs *kbuf) +{ + int err; + + err = put_user (kbuf->f_type, &ubuf->f_type); + err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize); + err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks); + err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree); + err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail); + err |= __put_user (kbuf->f_files, &ubuf->f_files); + err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree); + err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen); + err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]); + err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]); + return err; +} + +extern asmlinkage int sys_statfs(const char * path, struct statfs * buf); + +asmlinkage int +sys32_statfs(const char * path, struct statfs32 *buf) +{ + int ret; + struct statfs s; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_statfs((const char *)path, &s); + set_fs (old_fs); + if (put_statfs(buf, &s)) + return -EFAULT; + return ret; +} + +extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf); + +asmlinkage int +sys32_fstatfs(unsigned int fd, struct statfs32 *buf) +{ + int ret; + struct statfs s; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_fstatfs(fd, &s); + set_fs (old_fs); + if (put_statfs(buf, &s)) + return -EFAULT; + return ret; +} + +extern asmlinkage int +sys_getrusage(int who, struct rusage *ru); + +asmlinkage int +sys32_getrusage(int who, struct rusage32 *ru) +{ + struct rusage r; + int ret; + mm_segment_t old_fs = get_fs(); + + set_fs (KERNEL_DS); + ret = sys_getrusage(who, &r); + set_fs (old_fs); + if (put_rusage (ru, &r)) return -EFAULT; + return ret; +} + +static inline long +get_tv32(struct timeval *o, struct timeval32 *i) +{ + return (!access_ok(VERIFY_READ, i, sizeof(*i)) || + (__get_user(o->tv_sec, &i->tv_sec) | + __get_user(o->tv_usec, &i->tv_usec))); + return ENOSYS; +} + +static inline long +get_it32(struct itimerval *o, struct itimerval32 *i) +{ + return (!access_ok(VERIFY_READ, i, sizeof(*i)) || + (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) | + __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) | + __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) | + __get_user(o->it_value.tv_usec, &i->it_value.tv_usec))); + return ENOSYS; +} + +static inline long +put_tv32(struct timeval32 *o, struct timeval *i) +{ + return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || + (__put_user(i->tv_sec, &o->tv_sec) | + __put_user(i->tv_usec, &o->tv_usec))); +} + +static inline long +put_it32(struct itimerval32 *o, struct itimerval *i) +{ + return (!access_ok(VERIFY_WRITE, i, sizeof(*i)) || + (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) | + __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) | + __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) | + __put_user(i->it_value.tv_usec, &o->it_value.tv_usec))); + return ENOSYS; +} + +extern int do_getitimer(int which, struct itimerval *value); + +asmlinkage int +sys32_getitimer(int which, struct itimerval32 *it) +{ + struct itimerval kit; + int error; + + error = do_getitimer(which, &kit); + if (!error && put_it32(it, &kit)) + error = -EFAULT; + + return error; +} + +extern int do_setitimer(int which, struct itimerval *, struct itimerval *); + + +asmlinkage int +sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out) +{ + struct itimerval kin, kout; + int error; + + if (in) { + if (get_it32(&kin, in)) + return -EFAULT; + } else + memset(&kin, 0, sizeof(kin)); + + error = do_setitimer(which, &kin, out ? &kout : NULL); + if (error || !out) + return error; + if (put_it32(out, &kout)) + return -EFAULT; + + return 0; + +} +asmlinkage unsigned long +sys32_alarm(unsigned int seconds) +{ + struct itimerval it_new, it_old; + unsigned int oldalarm; + + it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0; + it_new.it_value.tv_sec = seconds; + it_new.it_value.tv_usec = 0; + do_setitimer(ITIMER_REAL, &it_new, &it_old); + oldalarm = it_old.it_value.tv_sec; + /* ehhh.. We can't return 0 if we have an alarm pending.. */ + /* And we'd better return too much than too little anyway */ + if (it_old.it_value.tv_usec) + oldalarm++; + return oldalarm; +} + +/* Translations due to time_t size differences. Which affects all + sorts of things, like timeval and itimerval. */ + + +extern struct timezone sys_tz; +extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz); + +asmlinkage int +sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz) +{ + if (tv) { + struct timeval ktv; + do_gettimeofday(&ktv); + if (put_tv32(tv, &ktv)) + return -EFAULT; + } + if (tz) { + if (copy_to_user(tz, &sys_tz, sizeof(sys_tz))) + return -EFAULT; + } + return 0; +} + +asmlinkage int +sys32_settimeofday(struct timeval32 *tv, struct timezone *tz) +{ + struct timeval ktv; + struct timezone ktz; + + if (tv) { + if (get_tv32(&ktv, tv)) + return -EFAULT; + } + if (tz) { + if (copy_from_user(&ktz, tz, sizeof(ktz))) + return -EFAULT; + } + + return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL); +} + +extern asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, + unsigned long offset_low, loff_t * result, + unsigned int origin); + +extern asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high, + unsigned int offset_low, loff_t * result, + unsigned int origin) +{ + return sys_llseek(fd, offset_high, offset_low, result, origin); +} + +struct iovec32 { unsigned int iov_base; int iov_len; }; + +typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *); + +static long +do_readv_writev32(int type, struct file *file, const struct iovec32 *vector, + u32 count) +{ + unsigned long tot_len; + struct iovec iovstack[UIO_FASTIOV]; + struct iovec *iov=iovstack, *ivp; + struct inode *inode; + long retval, i; + IO_fn_t fn; + + /* First get the "struct iovec" from user memory and + * verify all the pointers + */ + if (!count) + return 0; + if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + return -EFAULT; + if (count > UIO_MAXIOV) + return -EINVAL; + if (count > UIO_FASTIOV) { + iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); + if (!iov) + return -ENOMEM; + } + + tot_len = 0; + i = count; + ivp = iov; + while(i > 0) { + u32 len; + u32 buf; + + __get_user(len, &vector->iov_len); + __get_user(buf, &vector->iov_base); + tot_len += len; + ivp->iov_base = (void *)A(buf); + ivp->iov_len = (__kernel_size_t) len; + vector++; + ivp++; + i--; + } + + inode = file->f_dentry->d_inode; + /* VERIFY_WRITE actually means a read, as we write to user space */ + retval = locks_verify_area((type == VERIFY_WRITE + ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), + inode, file, file->f_pos, tot_len); + if (retval) { + if (iov != iovstack) + kfree(iov); + return retval; + } + + /* Then do the actual IO. Note that sockets need to be handled + * specially as they have atomicity guarantees and can handle + * iovec's natively + */ + if (inode->i_sock) { + int err; + err = sock_readv_writev(type, inode, file, iov, count, tot_len); + if (iov != iovstack) + kfree(iov); + return err; + } + + if (!file->f_op) { + if (iov != iovstack) + kfree(iov); + return -EINVAL; + } + /* VERIFY_WRITE actually means a read, as we write to user space */ + fn = file->f_op->read; + if (type == VERIFY_READ) + fn = (IO_fn_t) file->f_op->write; + ivp = iov; + while (count > 0) { + void * base; + int len, nr; + + base = ivp->iov_base; + len = ivp->iov_len; + ivp++; + count--; + nr = fn(file, base, len, &file->f_pos); + if (nr < 0) { + if (retval) + break; + retval = nr; + break; + } + retval += nr; + if (nr != len) + break; + } + if (iov != iovstack) + kfree(iov); + return retval; +} + +asmlinkage long +sys32_readv(int fd, struct iovec32 *vector, u32 count) +{ + struct file *file; + long ret = -EBADF; + + lock_kernel(); + file = fget(fd); + if(!file) + goto bad_file; + + if(!(file->f_mode & 1)) + goto out; + + ret = do_readv_writev32(VERIFY_WRITE, file, + vector, count); +out: + fput(file); +bad_file: + unlock_kernel(); + return ret; +} + +asmlinkage long +sys32_writev(int fd, struct iovec32 *vector, u32 count) +{ + struct file *file; + int ret = -EBADF; + + lock_kernel(); + file = fget(fd); + if(!file) + goto bad_file; + + if(!(file->f_mode & 2)) + goto out; + + ret = do_readv_writev32(VERIFY_READ, file, + vector, count); +out: + fput(file); +bad_file: + unlock_kernel(); + return ret; +} + +/* + * Ooo, nasty. We need here to frob 32-bit unsigned longs to + * 64-bit unsigned longs. + */ + +static inline int +get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset) +{ +#ifdef __MIPSEB__ + if (ufdset) { + unsigned long odd; + + if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32))) + return -EFAULT; + + odd = n & 1UL; + n &= ~1UL; + while (n) { + unsigned long h, l; + __get_user(l, ufdset); + __get_user(h, ufdset+1); + ufdset += 2; + *fdset++ = h << 32 | l; + n -= 2; + } + if (odd) + __get_user(*fdset, ufdset); + } else { + /* Tricky, must clear full unsigned long in the + * kernel fdset at the end, this makes sure that + * actually happens. + */ + memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32)); + } + return 0; +#else + <> +#endif +} + +static inline void +set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset) +{ + unsigned long odd; + + if (!ufdset) + return; + + odd = n & 1UL; + n &= ~1UL; + while (n) { + unsigned long h, l; + l = *fdset++; + h = l >> 32; + __put_user(l, ufdset); + __put_user(h, ufdset+1); + ufdset += 2; + n -= 2; + } + if (odd) + __put_user(*fdset, ufdset); +} + +/* + * We can actually return ERESTARTSYS instead of EINTR, but I'd + * like to be certain this leads to no problems. So I return + * EINTR just for safety. + * + * Update: ERESTARTSYS breaks at least the xview clock binary, so + * I'm trying ERESTARTNOHAND which restart only when you want to. + */ +#define MAX_SELECT_SECONDS \ + ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) + +asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, struct timeval32 *tvp) +{ + fd_set_bits fds; + char *bits; + unsigned long nn; + long timeout; + int ret, size; + + timeout = MAX_SCHEDULE_TIMEOUT; + if (tvp) { + time_t sec, usec; + + if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp))) + || (ret = __get_user(sec, &tvp->tv_sec)) + || (ret = __get_user(usec, &tvp->tv_usec))) + goto out_nofds; + + ret = -EINVAL; + if(sec < 0 || usec < 0) + goto out_nofds; + + if ((unsigned long) sec < MAX_SELECT_SECONDS) { + timeout = (usec + 1000000/HZ - 1) / (1000000/HZ); + timeout += sec * (unsigned long) HZ; + } + } + + ret = -EINVAL; + if (n < 0) + goto out_nofds; + if (n > current->files->max_fdset) + n = current->files->max_fdset; + + /* + * We need 6 bitmaps (in/out/ex for both incoming and outgoing), + * since we used fdset we need to allocate memory in units of + * long-words. + */ + ret = -ENOMEM; + size = FDS_BYTES(n); + bits = kmalloc(6 * size, GFP_KERNEL); + if (!bits) + goto out_nofds; + fds.in = (unsigned long *) bits; + fds.out = (unsigned long *) (bits + size); + fds.ex = (unsigned long *) (bits + 2*size); + fds.res_in = (unsigned long *) (bits + 3*size); + fds.res_out = (unsigned long *) (bits + 4*size); + fds.res_ex = (unsigned long *) (bits + 5*size); + + nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32)); + if ((ret = get_fd_set32(nn, fds.in, inp)) || + (ret = get_fd_set32(nn, fds.out, outp)) || + (ret = get_fd_set32(nn, fds.ex, exp))) + goto out; + zero_fd_set(n, fds.res_in); + zero_fd_set(n, fds.res_out); + zero_fd_set(n, fds.res_ex); + + ret = do_select(n, &fds, &timeout); + + if (tvp && !(current->personality & STICKY_TIMEOUTS)) { + time_t sec = 0, usec = 0; + if (timeout) { + sec = timeout / HZ; + usec = timeout % HZ; + usec *= (1000000/HZ); + } + put_user(sec, &tvp->tv_sec); + put_user(usec, &tvp->tv_usec); + } + + if (ret < 0) + goto out; + if (!ret) { + ret = -ERESTARTNOHAND; + if (signal_pending(current)) + goto out; + ret = 0; + } + + set_fd_set32(nn, inp, fds.res_in); + set_fd_set32(nn, outp, fds.res_out); + set_fd_set32(nn, exp, fds.res_ex); + +out: + kfree(bits); +out_nofds: + return ret; +} + + + +struct timespec32 { + int tv_sec; + int tv_nsec; +}; + +extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, + struct timespec *interval); + +asmlinkage int +sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval) +{ + struct timespec t; + int ret; + mm_segment_t old_fs = get_fs (); + + set_fs (KERNEL_DS); + ret = sys_sched_rr_get_interval(pid, &t); + set_fs (old_fs); + if (put_user (t.tv_sec, &interval->tv_sec) || + __put_user (t.tv_nsec, &interval->tv_nsec)) + return -EFAULT; + return ret; +} + + +extern asmlinkage int sys_nanosleep(struct timespec *rqtp, + struct timespec *rmtp); + +asmlinkage int +sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp) +{ + struct timespec t; + int ret; + mm_segment_t old_fs = get_fs (); + + if (get_user (t.tv_sec, &rqtp->tv_sec) || + __get_user (t.tv_nsec, &rqtp->tv_nsec)) + return -EFAULT; + + set_fs (KERNEL_DS); + ret = sys_nanosleep(&t, rmtp ? &t : NULL); + set_fs (old_fs); + if (rmtp && ret == -EINTR) { + if (__put_user (t.tv_sec, &rmtp->tv_sec) || + __put_user (t.tv_nsec, &rmtp->tv_nsec)) + return -EFAULT; + } + return ret; +} diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/mips64_ksyms.c linux/arch/mips64/kernel/mips64_ksyms.c --- v2.3.99-pre8/linux/arch/mips64/kernel/mips64_ksyms.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/mips64_ksyms.c Sat May 13 08:30:17 2000 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -56,8 +57,6 @@ EXPORT_SYMBOL_NOVERS(strpbrk); EXPORT_SYMBOL(_clear_page); -EXPORT_SYMBOL(local_bh_count); -EXPORT_SYMBOL(local_irq_count); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(kernel_thread); @@ -83,10 +82,19 @@ */ EXPORT_SYMBOL(_flush_page_to_ram); EXPORT_SYMBOL(_flush_cache_all); +#ifndef CONFIG_COHERENT_IO EXPORT_SYMBOL(_dma_cache_wback_inv); EXPORT_SYMBOL(_dma_cache_inv); +#endif EXPORT_SYMBOL(invalid_pte_table); + +/* + * Semaphore stuff + */ +EXPORT_SYMBOL(__down_read); +EXPORT_SYMBOL(__down_write); +EXPORT_SYMBOL(__rwsem_wake); /* * Base address of ports for Intel style I/O. diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/proc.c linux/arch/mips64/kernel/proc.c --- v2.3.99-pre8/linux/arch/mips64/kernel/proc.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/proc.c Sat May 13 08:30:17 2000 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,7 @@ len += sprintf(buffer + len, "BogoMIPS\t\t: %lu.%02lu\n", (loops_per_sec + 2500) / 500000, ((loops_per_sec + 2500) / 5000) % 100); + len += sprintf(buffer + len, "Number of cpus\t\t: %d\n", smp_num_cpus); #if defined (__MIPSEB__) len += sprintf(buffer + len, "byteorder\t\t: big endian\n"); #endif @@ -68,4 +70,9 @@ len += sprintf(buffer + len, fmt, 'I', vcei_count); return len; +} + +void init_irq_proc(void) +{ + /* Nothing, for now. */ } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/process.c linux/arch/mips64/kernel/process.c --- v2.3.99-pre8/linux/arch/mips64/kernel/process.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/process.c Mon May 15 12:10:26 2000 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.5 2000/01/29 01:41:59 ralf Exp $ +/* $Id: process.c,v 1.4 2000/01/16 01:34:01 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -33,6 +33,7 @@ asmlinkage int cpu_idle(void) { /* endless idle loop with no priority at all */ + init_idle(); current->priority = 0; current->counter = -100; while (1) { @@ -51,20 +52,20 @@ void exit_thread(void) { /* Forget lazy fpu state */ - if (last_task_used_math == current) { + if (IS_FPU_OWNER()) { set_cp0_status(ST0_CU1, ST0_CU1); __asm__ __volatile__("cfc1\t$0,$31"); - last_task_used_math = NULL; + CLEAR_FPU_OWNER(); } } void flush_thread(void) { /* Forget lazy fpu state */ - if (last_task_used_math == current) { + if (IS_FPU_OWNER()) { set_cp0_status(ST0_CU1, ST0_CU1); __asm__ __volatile__("cfc1\t$0,$31"); - last_task_used_math = NULL; + CLEAR_FPU_OWNER(); } } @@ -76,8 +77,7 @@ childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32; - if (last_task_used_math == current) { - set_cp0_status(ST0_CU1, ST0_CU1); + if (IS_FPU_OWNER()) { save_fp(p); } /* set up new TSS. */ diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/ptrace.c linux/arch/mips64/kernel/ptrace.c --- v2.3.99-pre8/linux/arch/mips64/kernel/ptrace.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/ptrace.c Sat May 13 08:30:17 2000 @@ -8,13 +8,561 @@ * Copyright (C) Linus Torvalds * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle * Copyright (C) 1996 David S. Miller + * Copyright (C) 2000 Ulf Carlsson * * At this time Linux/MIPS64 only supports syscall tracing, even for 32-bit * binaries. */ +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Tracing a 32-bit process with a 64-bit strace and vice verca will not + work. I don't know how to fix this. */ + +asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) +{ + struct task_struct *child; + int ret; + + lock_kernel(); +#if 0 + printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", + (int) request, (int) pid, (unsigned long) addr, + (unsigned long) data); +#endif + ret = -EPERM; + if (request == PTRACE_TRACEME) { + /* are we already being traced? */ + if (current->flags & PF_PTRACED) + goto out; + /* set the ptrace bit in the process flags. */ + current->flags |= PF_PTRACED; + ret = 0; + goto out; + } + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) + goto out; + + ret = -EPERM; + if (pid == 1) /* you may not mess with init */ + goto out_tsk; + + if (request == PTRACE_ATTACH) { + if (child == current) + goto out_tsk; + if ((!child->dumpable || + (current->uid != child->euid) || + (current->uid != child->suid) || + (current->uid != child->uid) || + (current->gid != child->egid) || + (current->gid != child->sgid) || + (!cap_issubset(child->cap_permitted, current->cap_permitted)) || + (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) + goto out_tsk; + /* the same process cannot be attached many times */ + if (child->flags & PF_PTRACED) + goto out_tsk; + child->flags |= PF_PTRACED; + + write_lock_irq(&tasklist_lock); + if (child->p_pptr != current) { + REMOVE_LINKS(child); + child->p_pptr = current; + SET_LINKS(child); + } + write_unlock_irq(&tasklist_lock); + + send_sig(SIGSTOP, child, 1); + ret = 0; + goto out_tsk; + } + ret = -ESRCH; + if (!(child->flags & PF_PTRACED)) + goto out_tsk; + if (child->state != TASK_STOPPED) { + if (request != PTRACE_KILL) + goto out_tsk; + } + if (child->p_pptr != current) + goto out_tsk; + + switch (request) { + /* when I and D space are separate, these will need to be fixed. */ + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA: { + unsigned int tmp; + int copied; + + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + ret = -EIO; + if (copied != sizeof(tmp)) + break; + ret = put_user(tmp, (unsigned int *) data); + break; + } + + /* read the word at location addr in the USER area. */ + case PTRACE_PEEKUSR: { + struct pt_regs *regs; + unsigned int tmp; + + regs = (struct pt_regs *) ((unsigned long) child + + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); + ret = 0; + + switch (addr) { + case 0 ... 31: + tmp = regs->regs[addr]; + break; + case FPR_BASE ... FPR_BASE + 31: + if (child->used_math) { +#ifndef CONFIG_SMP + if (last_task_used_math == child) { + set_cp0_status(ST0_CU1, ST0_CU1); + save_fp(child); + set_cp0_status(ST0_CU1, 0); + last_task_used_math = NULL; + } +#endif + tmp = child->thread.fpu.hard.fp_regs[addr - 32]; + } else { + tmp = -EIO; + } + break; + case PC: + tmp = regs->cp0_epc; + break; + case CAUSE: + tmp = regs->cp0_cause; + break; + case BADVADDR: + tmp = regs->cp0_badvaddr; + break; + case MMHI: + tmp = regs->hi; + break; + case MMLO: + tmp = regs->lo; + break; + case FPC_CSR: + tmp = child->thread.fpu.hard.control; + break; + case FPC_EIR: { /* implementation / version register */ + unsigned int flags; + __save_flags(flags); + set_cp0_status(ST0_CU1, ST0_CU1); + __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); + __restore_flags(flags); + break; + } + default: + tmp = 0; + ret = -EIO; + goto out_tsk; + } + ret = put_user(tmp, (unsigned *) data); + break; + } + /* when I and D space are separate, this will have to be fixed. */ + case PTRACE_POKETEXT: /* write the word at location addr. */ + case PTRACE_POKEDATA: + ret = 0; + if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) + break; + ret = -EIO; + break; + + case PTRACE_POKEUSR: { + struct pt_regs *regs; + ret = 0; + regs = (struct pt_regs *) ((unsigned long) child + + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); + + switch (addr) { + case 0 ... 31: + regs->regs[addr] = data; + break; + case FPR_BASE ... FPR_BASE + 31: { + unsigned long *fregs; + if (child->used_math) { +#ifndef CONFIG_SMP + if (last_task_used_math == child) { + set_cp0_status(ST0_CU1, ST0_CU1); + save_fp(child); + set_cp0_status(ST0_CU1, 0); + last_task_used_math = NULL; + regs->cp0_status &= ~ST0_CU1; + } +#endif + } else { + /* FP not yet used */ + memset(&child->thread.fpu.hard, ~0, + sizeof(child->thread.fpu.hard)); + child->thread.fpu.hard.control = 0; + } + fregs = child->thread.fpu.hard.fp_regs; + fregs[addr - FPR_BASE] = data; + break; + } + case PC: + regs->cp0_epc = data; + break; + case MMHI: + regs->hi = data; + break; + case MMLO: + regs->lo = data; + break; + case FPC_CSR: + child->thread.fpu.hard.control = data; + break; + default: + /* The rest are not allowed. */ + ret = -EIO; + break; + } + goto out; + } + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: { /* restart after signal. */ + ret = -EIO; + if ((unsigned int) data > _NSIG) + break; + if (request == PTRACE_SYSCALL) + child->flags |= PF_TRACESYS; + else + child->flags &= ~PF_TRACESYS; + child->exit_code = data; + wake_up_process(child); + ret = 0; + break; + } + +/* + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to + * exit. + */ + case PTRACE_KILL: { + if (child->state == TASK_ZOMBIE) /* already dead */ + break; + child->exit_code = SIGKILL; + wake_up_process(child); + break; + } + + case PTRACE_DETACH: { /* detach a process that was attached. */ + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + child->flags &= ~(PF_PTRACED|PF_TRACESYS); + child->exit_code = data; + write_lock_irq(&tasklist_lock); + REMOVE_LINKS(child); + child->p_pptr = child->p_opptr; + SET_LINKS(child); + write_unlock_irq(&tasklist_lock); + wake_up_process(child); + ret = 0; + break; + } + + default: + ret = -EIO; + break; + } + +out_tsk: + free_task_struct(child); +out: + unlock_kernel(); + return ret; +} + +asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +{ + struct task_struct *child; + int ret; + + lock_kernel(); +#if 0 + printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", + (int) request, (int) pid, (unsigned long) addr, + (unsigned long) data); +#endif + ret = -EPERM; + if (request == PTRACE_TRACEME) { + /* are we already being traced? */ + if (current->flags & PF_PTRACED) + goto out; + /* set the ptrace bit in the process flags. */ + current->flags |= PF_PTRACED; + ret = 0; + goto out; + } + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) + goto out; + + ret = -EPERM; + if (pid == 1) /* you may not mess with init */ + goto out; + + if (request == PTRACE_ATTACH) { + if (child == current) + goto out_tsk; + if ((!child->dumpable || + (current->uid != child->euid) || + (current->uid != child->suid) || + (current->uid != child->uid) || + (current->gid != child->egid) || + (current->gid != child->sgid) || + (!cap_issubset(child->cap_permitted, current->cap_permitted)) || + (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) + goto out_tsk; + /* the same process cannot be attached many times */ + if (child->flags & PF_PTRACED) + goto out_tsk; + child->flags |= PF_PTRACED; + + write_lock_irq(&tasklist_lock); + if (child->p_pptr != current) { + REMOVE_LINKS(child); + child->p_pptr = current; + SET_LINKS(child); + } + write_unlock_irq(&tasklist_lock); + + send_sig(SIGSTOP, child, 1); + ret = 0; + goto out_tsk; + } + ret = -ESRCH; + if (!(child->flags & PF_PTRACED)) + goto out_tsk; + if (child->state != TASK_STOPPED) { + if (request != PTRACE_KILL) + goto out_tsk; + } + if (child->p_pptr != current) + goto out_tsk; + + switch (request) { + /* when I and D space are separate, these will need to be fixed. */ + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA: { + unsigned long tmp; + int copied; + + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + ret = -EIO; + if (copied != sizeof(tmp)) + break; + ret = put_user(tmp,(unsigned long *) data); + break; + } + + /* read the word at location addr in the USER area. */ + case PTRACE_PEEKUSR: { + struct pt_regs *regs; + unsigned long tmp; + + regs = (struct pt_regs *) ((unsigned long) child + + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); + ret = 0; + + switch (addr) { + case 0 ... 31: + tmp = regs->regs[addr]; + break; + case FPR_BASE ... FPR_BASE + 31: + if (child->used_math) { +#ifndef CONFIG_SMP + if (last_task_used_math == child) { + set_cp0_status(ST0_CU1, ST0_CU1); + save_fp(child); + set_cp0_status(ST0_CU1, 0); + last_task_used_math = NULL; + } +#endif + tmp = child->thread.fpu.hard.fp_regs[addr - 32]; + } else { + tmp = -EIO; + } + break; + case PC: + tmp = regs->cp0_epc; + break; + case CAUSE: + tmp = regs->cp0_cause; + break; + case BADVADDR: + tmp = regs->cp0_badvaddr; + break; + case MMHI: + tmp = regs->hi; + break; + case MMLO: + tmp = regs->lo; + break; + case FPC_CSR: + tmp = child->thread.fpu.hard.control; + break; + case FPC_EIR: { /* implementation / version register */ + unsigned int flags; + __save_flags(flags); + set_cp0_status(ST0_CU1, ST0_CU1); + __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); + __restore_flags(flags); + break; + } + default: + tmp = 0; + ret = -EIO; + goto out_tsk; + } + ret = put_user(tmp, (unsigned long *) data); + break; + } + /* when I and D space are separate, this will have to be fixed. */ + case PTRACE_POKETEXT: /* write the word at location addr. */ + case PTRACE_POKEDATA: + ret = 0; + if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) + break; + ret = -EIO; + break; + + case PTRACE_POKEUSR: { + struct pt_regs *regs; + ret = 0; + regs = (struct pt_regs *) ((unsigned long) child + + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); + + switch (addr) { + case 0 ... 31: + regs->regs[addr] = data; + break; + case FPR_BASE ... FPR_BASE + 31: { + unsigned long *fregs; + if (child->used_math) { +#ifndef CONFIG_SMP + if (last_task_used_math == child) { + set_cp0_status(ST0_CU1, ST0_CU1); + save_fp(child); + set_cp0_status(ST0_CU1, 0); + last_task_used_math = NULL; + regs->cp0_status &= ~ST0_CU1; + } +#endif + } else { + /* FP not yet used */ + memset(&child->thread.fpu.hard, ~0, + sizeof(child->thread.fpu.hard)); + child->thread.fpu.hard.control = 0; + } + fregs = child->thread.fpu.hard.fp_regs; + fregs[addr - FPR_BASE] = data; + break; + } + case PC: + regs->cp0_epc = data; + break; + case MMHI: + regs->hi = data; + break; + case MMLO: + regs->lo = data; + break; + case FPC_CSR: + child->thread.fpu.hard.control = data; + break; + default: + /* The rest are not allowed. */ + ret = -EIO; + break; + } + goto out; + } + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: { /* restart after signal. */ + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + if (request == PTRACE_SYSCALL) + child->flags |= PF_TRACESYS; + else + child->flags &= ~PF_TRACESYS; + child->exit_code = data; + wake_up_process(child); + ret = 0; + break; + } + +/* + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to + * exit. + */ + case PTRACE_KILL: { + if (child->state == TASK_ZOMBIE) /* already dead */ + break; + child->exit_code = SIGKILL; + wake_up_process(child); + break; + } + + case PTRACE_DETACH: { /* detach a process that was attached. */ + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + child->flags &= ~(PF_PTRACED|PF_TRACESYS); + child->exit_code = data; + write_lock_irq(&tasklist_lock); + REMOVE_LINKS(child); + child->p_pptr = child->p_opptr; + SET_LINKS(child); + write_unlock_irq(&tasklist_lock); + wake_up_process(child); + ret = 0; + break; + } + + default: + ret = -EIO; + break; + } + +out_tsk: + free_task_struct(child); +out: + unlock_kernel(); + return ret; +} asmlinkage void syscall_trace(void) { diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/r4k_cache.S linux/arch/mips64/kernel/r4k_cache.S --- v2.3.99-pre8/linux/arch/mips64/kernel/r4k_cache.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/r4k_cache.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: r4k_cache.S,v 1.1 1999/12/04 03:59:00 ralf Exp $ +/* $Id: r4k_cache.S,v 1.1 1999/10/10 18:49:17 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/r4k_fpu.S linux/arch/mips64/kernel/r4k_fpu.S --- v2.3.99-pre8/linux/arch/mips64/kernel/r4k_fpu.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/r4k_fpu.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: r4k_fpu.S,v 1.1 1999/09/28 22:25:52 ralf Exp $ +/* $Id: r4k_fpu.S,v 1.1 1999/09/27 16:01:38 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/r4k_genex.S linux/arch/mips64/kernel/r4k_genex.S --- v2.3.99-pre8/linux/arch/mips64/kernel/r4k_genex.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/r4k_genex.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: r4k_genex.S,v 1.3 2000/01/20 23:32:21 ralf Exp $ +/* $Id: r4k_genex.S,v 1.3 1999/11/23 17:12:49 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -69,6 +69,14 @@ NESTED(handle_\exception, PT_SIZE, sp) .set noat SAVE_ALL +#if DEBUG_MIPS64 +jal dodebug2 +ld $4, PT_R4(sp) +ld $5, PT_R5(sp) +ld $6, PT_R6(sp) +ld $7, PT_R7(sp) +ld $2, PT_R2(sp) +#endif __BUILD_clear_\clear .set at __BUILD_\verbose \exception diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/r4k_switch.S linux/arch/mips64/kernel/r4k_switch.S --- v2.3.99-pre8/linux/arch/mips64/kernel/r4k_switch.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/r4k_switch.S Sat May 13 08:30:17 2000 @@ -9,6 +9,7 @@ * Copyright (C) 1994, 1995, 1996, by Andreas Busse * Copyright (C) 1999 Silicon Graphics, Inc. */ +#include #include #include #include @@ -43,8 +44,14 @@ */ move $28, a1 cpu_restore_nonscratch $28 +#ifndef CONFIG_SMP daddiu t0, $28, KERNEL_STACK_SIZE-32 sd t0, kernelsp +#else + mtc0 a1, CP0_WATCHLO + dsrl32 a1, a1, 0 + mtc0 a1, CP0_WATCHHI +#endif mfc0 t1, CP0_STATUS /* Do we really need this? */ li a3, 0xff00 and t1, a3 @@ -73,7 +80,7 @@ beqz a0, 2f # Save floating point state nor t3, zero, t3 - lw t1, ST_OFF(a0) # last thread looses fpu + ld t1, ST_OFF(a0) # last thread looses fpu and t1, t3 sd t1, ST_OFF(a0) sll t2, t1, 5 @@ -84,6 +91,8 @@ fpu_save_16even a0 t1 # clobbers t1 2: + beqz a1, 3f + sll t0, t0, 5 # load new fp state bgez t0, 1f ldc1 $f0, (THREAD_FPU + 0x00)($28) @@ -91,6 +100,7 @@ 1: .set reorder fpu_restore_16even $28, t0 # clobbers t0 +3: jr ra END(lazy_fpu_switch) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/r4k_tlb_debug.c linux/arch/mips64/kernel/r4k_tlb_debug.c --- v2.3.99-pre8/linux/arch/mips64/kernel/r4k_tlb_debug.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/r4k_tlb_debug.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: r4k_tlb_debug.c,v 1.3 2000/01/29 01:41:59 ralf Exp $ +/* $Id: r4k_tlb_debug.c,v 1.2 2000/01/17 23:32:46 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/r4k_tlb_glue.S linux/arch/mips64/kernel/r4k_tlb_glue.S --- v2.3.99-pre8/linux/arch/mips64/kernel/r4k_tlb_glue.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/r4k_tlb_glue.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: r4k_tlb_glue.S,v 1.2 2000/01/17 23:32:46 ralf Exp $ +/* $Id: r4k_tlb_glue.S,v 1.5 1999/11/23 17:12:49 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -23,10 +23,26 @@ END(__tlb_refill_debug_tramp) __FINIT - .macro tlb_handler name + .macro __BUILD_cli + CLI + .endm + + .macro __BUILD_sti + STI + .endm + + .macro tlb_handler name interruptible NESTED(__\name, PT_SIZE, sp) SAVE_ALL - CLI +#if DEBUG_MIPS64 +jal dodebug2 +ld $4, PT_R4(sp) +ld $5, PT_R5(sp) +ld $6, PT_R6(sp) +ld $7, PT_R7(sp) +ld $2, PT_R2(sp) +#endif + __BUILD_\interruptible dmfc0 t0, CP0_BADVADDR sd t0, PT_BVADDR(sp) move a0, sp @@ -35,8 +51,8 @@ END(__\name) .endm - tlb_handler tlb_refill_debug - tlb_handler xtlb_refill_debug - tlb_handler xtlb_mod_debug - tlb_handler xtlb_tlbl_debug - tlb_handler xtlb_tlbs_debug + tlb_handler tlb_refill_debug cli + tlb_handler xtlb_refill_debug cli + tlb_handler xtlb_mod_debug sti + tlb_handler xtlb_tlbl_debug sti + tlb_handler xtlb_tlbs_debug sti diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/scall_64.S linux/arch/mips64/kernel/scall_64.S --- v2.3.99-pre8/linux/arch/mips64/kernel/scall_64.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/scall_64.S Sat May 13 08:30:17 2000 @@ -22,9 +22,6 @@ /* This duplicates the definition from */ #define SIGILL 4 /* Illegal instruction (ANSI). */ -/* Highest syscall handled here. */ -#define MAX_SYSCALL_NO __NR_Linux + __NR_Linux_syscalls - #ifndef CONFIG_MIPS32_COMPAT #define handle_sys64 handle_sys #endif @@ -35,18 +32,19 @@ #ifndef CONFIG_MIPS32_COMPAT .set noat SAVE_SOME + STI .set at #endif ld t1, PT_EPC(sp) # skip syscall on return - sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number + subu t0, v0, __NR_Linux # check syscall number + sltiu t0, t0, __NR_Linux_syscalls + 1 daddiu t1, 4 # skip to next instruction beqz t0, illegal_syscall sd t1, PT_EPC(sp) - dsll t0, v0, 3 + dsll t0, v0, 3 # offset into table ld t2, (sys_call_table - (__NR_Linux * 8))(t0) # syscall routine - beqz t2, illegal_syscall; sd a3, PT_R26(sp) # save a3 for syscall restarting @@ -163,7 +161,7 @@ PTR sys_ni_syscall /* ptrace */ PTR sys_alarm PTR sys_fstat - PTR sys_ni_syscall + PTR sys_pause PTR sys_utime /* 4030 */ PTR sys_ni_syscall PTR sys_ni_syscall @@ -345,3 +343,5 @@ PTR sys_ni_syscall PTR sys_ni_syscall PTR sys_pivot_root /* 4210 */ + PTR sys_mincore + PTR sys_madvise diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/scall_o32.S linux/arch/mips64/kernel/scall_o32.S --- v2.3.99-pre8/linux/arch/mips64/kernel/scall_o32.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/scall_o32.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: scall_o32.S,v 1.8 2000/02/23 00:41:00 ralf Exp $ +/* $Id: scall_o32.S,v 1.18 2000/03/27 21:04:13 ulfc Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -35,23 +35,26 @@ SAVE_SOME STI .set at - SAVE_ALL - ld a1, PT_R2(sp) - PRINT("Got syscall %d\n") - RESTORE_ALL - +#if DEBUG_MIPS64 + jal dodebug + ld $4, PT_R4(sp) + ld $5, PT_R5(sp) + ld $6, PT_R6(sp) + ld $7, PT_R7(sp) + ld $2, PT_R2(sp) +#endif ld t1, PT_EPC(sp) # skip syscall on return - sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number + subu t0, v0, __NR_Linux32 # check syscall number + sltiu t0, t0, __NR_Linux32_syscalls + 1 daddiu t1, 4 # skip to next instruction beqz t0, not_o32_scall sd t1, PT_EPC(sp) /* XXX Put both in one cacheline, should save a bit. */ - dsll t0, v0, 3 + dsll t0, v0, 3 # offset into table ld t2, (sys_call_table - (__NR_Linux32 * 8))(t0) # syscall routine lbu t3, (sys_narg_table - __NR_Linux32)(v0) # number of arguments - beqz t2, illegal_syscall; subu t0, t3, 5 # 5 or more arguments? sd a3, PT_R26(sp) # save a3 for syscall restarting @@ -72,7 +75,7 @@ negu v0 # error sd v0, PT_R0(sp) # set flag for syscall restarting 1: sd v0, PT_R2(sp) # result - + FEXPORT(o32_ret_from_sys_call) lw t0, softirq_state lw t1, softirq_state+4 # unused delay slot @@ -110,6 +113,11 @@ trace_a_syscall: SAVE_STATIC + sd a4, PT_R8(sp) + sd a5, PT_R9(sp) + sd a6, PT_R10(sp) + sd a7, PT_R11(sp) + sd t2,PT_R1(sp) jal syscall_trace ld t2,PT_R1(sp) @@ -118,6 +126,9 @@ ld a1, PT_R5(sp) ld a2, PT_R6(sp) ld a3, PT_R7(sp) + ld a4, PT_R8(sp) + ld a5, PT_R9(sp) + jalr t2 li t0, -EMAXERRNO - 1 # error? @@ -130,7 +141,7 @@ 1: sd v0, PT_R2(sp) # result jal syscall_trace - j ret_from_sys_call + j o32_ret_from_sys_call /* ------------------------------------------------------------------------ */ @@ -197,12 +208,12 @@ sys sys_read 3 sys sys_write 3 sys sys_open 3 /* 4005 */ - sys sys_close 3 + sys sys_close 1 sys sys_waitpid 3 sys sys_creat 2 sys sys_link 2 sys sys_unlink 1 /* 4010 */ - sys sys_execve 0 + sys sys32_execve 0 sys sys_chdir 1 sys sys_time 1 sys sys_mknod 3 @@ -217,10 +228,10 @@ sys sys_setuid 1 sys sys_getuid 0 sys sys_stime 1 /* 4025 */ - sys sys_ni_syscall 0 /* ptrace */ - sys sys_alarm 1 + sys sys32_ptrace 4 + sys sys32_alarm 1 sys sys_fstat 2 - sys sys_ni_syscall 0 + sys sys_pause 0 sys sys_utime 2 /* 4030 */ sys sys_ni_syscall 0 sys sys_ni_syscall 0 @@ -245,7 +256,7 @@ sys sys_acct 0 sys sys_umount 2 sys sys_ni_syscall 0 - sys sys_ioctl 3 + sys sys32_ioctl 3 sys sys_fcntl 3 /* 4055 */ sys sys_ni_syscall 2 sys sys_setpgid 2 @@ -266,11 +277,11 @@ sys sys32_sigsuspend 0 sys sys32_sigpending 1 sys sys_sethostname 2 - sys sys_setrlimit 2 /* 4075 */ - sys sys_old_getrlimit 2 - sys sys_getrusage 2 - sys sys_gettimeofday 2 - sys sys_settimeofday 2 + sys sys32_setrlimit 2 /* 4075 */ + sys sys32_getrlimit 2 + sys sys32_getrusage 2 + sys sys32_gettimeofday 2 + sys sys32_settimeofday 2 sys sys_getgroups 2 /* 4080 */ sys sys_setgroups 2 sys sys_ni_syscall 0 /* old_select */ @@ -280,7 +291,7 @@ sys sys_uselib 1 sys sys_swapon 2 sys sys_reboot 3 - sys old_readdir 3 + sys sys32_readdir 3 sys sys_mmap 6 /* 4090 */ sys sys_munmap 2 sys sys_truncate 2 @@ -290,13 +301,13 @@ sys sys_getpriority 2 sys sys_setpriority 3 sys sys_ni_syscall 0 - sys sys_statfs 2 - sys sys_fstatfs 2 /* 4100 */ + sys sys32_statfs 2 + sys sys32_fstatfs 2 /* 4100 */ sys sys_ni_syscall 0 /* sys_ioperm */ sys sys_socketcall 2 sys sys_syslog 3 - sys sys_setitimer 3 - sys sys_getitimer 2 /* 4105 */ + sys sys32_setitimer 3 + sys sys32_getitimer 2 /* 4105 */ sys sys32_newstat 2 sys sys32_newlstat 2 sys sys32_newfstat 2 @@ -305,7 +316,7 @@ sys sys_vhangup 0 sys sys_ni_syscall 0 /* was sys_idle */ sys sys_ni_syscall 0 /* sys_vm86 */ - sys sys_wait4 4 + sys sys32_wait4 4 sys sys_swapoff 1 /* 4115 */ sys sys_sysinfo 1 sys sys_ipc 6 @@ -317,7 +328,7 @@ sys sys_ni_syscall 0 /* sys_modify_ldt */ sys sys_adjtimex 1 sys sys_mprotect 3 /* 4125 */ - sys sys_sigprocmask 3 + sys sys32_sigprocmask 3 sys sys_create_module 2 sys sys_init_module 5 sys sys_delete_module 1 @@ -331,13 +342,13 @@ sys sys_ni_syscall 0 /* for afs_syscall */ sys sys_setfsuid 1 sys sys_setfsgid 1 - sys sys_llseek 5 /* 4140 */ - sys sys_getdents 3 - sys sys_select 5 + sys sys32_llseek 5 /* 4140 */ + sys sys32_getdents 3 + sys sys32_select 5 sys sys_flock 2 sys sys_msync 3 - sys sys_readv 3 /* 4145 */ - sys sys_writev 3 + sys sys32_readv 3 /* 4145 */ + sys sys32_writev 3 sys sys_cacheflush 3 sys sys_cachectl 3 sys sys_sysmips 4 @@ -356,8 +367,8 @@ sys sys_sched_yield 0 sys sys_sched_get_priority_max 1 sys sys_sched_get_priority_min 1 - sys sys_sched_rr_get_interval 2 /* 4165 */ - sys sys_nanosleep 2 + sys sys32_sched_rr_get_interval 2 /* 4165 */ + sys sys32_nanosleep 2 sys sys_mremap 4 sys sys_accept 3 sys sys_bind 3 @@ -408,6 +419,8 @@ sys sys_lstat64 3 sys sys_fstat64 3 /* 4210 */ sys sys_pivot_root 2 + sys sys_mincore 3 + sys sys_madvise 3 .endm .macro sys function, nargs diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/setup.c linux/arch/mips64/kernel/setup.c --- v2.3.99-pre8/linux/arch/mips64/kernel/setup.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/setup.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.7 2000/02/04 07:40:24 ralf Exp $ +/* $Id: setup.c,v 1.9 2000/03/14 01:39:27 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -37,10 +37,13 @@ #include #ifdef CONFIG_SGI_IP27 +/* XXX Origin garbage has no business in this file */ #include #endif -struct mips_cpuinfo boot_cpu_data; +#ifndef CONFIG_SMP +struct cpuinfo_mips cpu_data[1]; +#endif #ifdef CONFIG_VT struct screen_info screen_info; @@ -102,7 +105,10 @@ * mips_io_port_base is the begin of the address space to which x86 style * I/O ports are mapped. */ +#ifdef CONFIG_SGI_IP27 +/* XXX Origin garbage has no business in this file */ unsigned long mips_io_port_base = IO_BASE; +#endif extern void ip22_setup(void); extern void ip27_setup(void); @@ -183,4 +189,6 @@ *memory_start_p = initrd_end; } #endif + + paging_init(); } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/signal.c linux/arch/mips64/kernel/signal.c --- v2.3.99-pre8/linux/arch/mips64/kernel/signal.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/signal.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.5 2000/02/04 07:40:24 ralf Exp $ +/* $Id: signal.c,v 1.4 2000/01/17 23:32:46 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -26,6 +26,7 @@ #include #include #include +#include #define DEBUG_SIG 0 @@ -37,6 +38,35 @@ extern asmlinkage int save_fp_context(struct sigcontext *sc); extern asmlinkage int restore_fp_context(struct sigcontext *sc); +static inline int store_fp_context(struct sigcontext *sc) +{ + unsigned int fcr0; + int err = 0; + + err |= __copy_to_user(&sc->sc_fpregs[0], + ¤t->thread.fpu.hard.fp_regs[0], NUM_FPU_REGS * + sizeof(unsigned long)); + err |= __copy_to_user(&sc->sc_fpc_csr, ¤t->thread.fpu.hard.control, + sizeof(unsigned int)); + __asm__ __volatile__("cfc1 %0, $0\n\t" : "=r" (fcr0)); + err |= __copy_to_user(&sc->sc_fpc_eir, &fcr0, sizeof(unsigned int)); + + return err; +} + +static inline int refill_fp_context(struct sigcontext *sc) +{ + int err = 0; + + if (verify_area(VERIFY_READ, sc, sizeof(*sc))) + return -EFAULT; + err |= __copy_from_user(¤t->thread.fpu.hard.fp_regs[0], + &sc->sc_fpregs[0], NUM_FPU_REGS * sizeof(unsigned long)); + err |= __copy_from_user(¤t->thread.fpu.hard.control, &sc->sc_fpc_csr, + sizeof(unsigned int)); + return err; +} + /* * Atomically swap in the new signal mask, and wait for a signal. */ @@ -180,8 +210,12 @@ err |= __get_user(owned_fp, &sc->sc_ownedfp); if (owned_fp) { - err |= restore_fp_context(sc); - last_task_used_math = current; + if (IS_FPU_OWNER()) { + CLEAR_FPU_OWNER(); + regs->cp0_status &= ~ST0_CU1; + } + current->used_math = 1; + err |= refill_fp_context(sc); } return err; @@ -281,11 +315,9 @@ static int inline setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) { - int owned_fp; int err = 0; err |= __put_user(regs->cp0_epc, &sc->sc_pc); - err |= __put_user(regs->cp0_status, &sc->sc_status); #define save_gp_reg(i) { \ err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \ @@ -306,16 +338,19 @@ err |= __put_user(regs->cp0_cause, &sc->sc_cause); err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); - owned_fp = (current == last_task_used_math); - err |= __put_user(owned_fp, &sc->sc_ownedfp); - if (current->used_math) { /* fp is active. */ - set_cp0_status(ST0_CU1, ST0_CU1); - err |= save_fp_context(sc); - last_task_used_math = NULL; - regs->cp0_status &= ~ST0_CU1; + if (IS_FPU_OWNER()) { + lazy_fpu_switch(current, 0); + CLEAR_FPU_OWNER(); + regs->cp0_status &= ~ST0_CU1; + } + err |= __put_user(1, &sc->sc_ownedfp); + err |= store_fp_context(sc); current->used_math = 0; + } else { + err |= __put_user(0, &sc->sc_ownedfp); } + err |= __put_user(regs->cp0_status, &sc->sc_status); return err; } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/signal32.c linux/arch/mips64/kernel/signal32.c --- v2.3.99-pre8/linux/arch/mips64/kernel/signal32.c Thu Mar 2 14:36:22 2000 +++ linux/arch/mips64/kernel/signal32.c Mon May 15 12:10:26 2000 @@ -1,4 +1,4 @@ -/* $Id: signal32.c,v 1.2 2000/02/18 00:03:48 ralf Exp $ +/* $Id: signal32.c,v 1.4 2000/03/15 22:46:55 kanoj Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -25,6 +25,7 @@ #include #include #include +#include #define DEBUG_SIG 0 @@ -38,12 +39,11 @@ /* 32-bit compatibility types */ -#define _NSIG32 128 #define _NSIG32_BPW 32 -#define _NSIG_WORDS (_NSIG / _NSIG_BPW) +#define _NSIG32_WORDS (_NSIG / _NSIG32_BPW) typedef struct { - unsigned int sig[_NSIG_WORDS]; + unsigned int sig[_NSIG32_WORDS]; } sigset32_t; typedef unsigned int __sighandler32_t; @@ -65,6 +65,35 @@ } stack32_t; +static inline int store_fp_context(struct sigcontext *sc) +{ + unsigned int fcr0; + int err = 0; + + err |= __copy_to_user(&sc->sc_fpregs[0], + ¤t->thread.fpu.hard.fp_regs[0], NUM_FPU_REGS * + sizeof(unsigned long)); + err |= __copy_to_user(&sc->sc_fpc_csr, ¤t->thread.fpu.hard.control, + sizeof(unsigned int)); + __asm__ __volatile__("cfc1 %0, $0\n\t" : "=r" (fcr0)); + err |= __copy_to_user(&sc->sc_fpc_eir, &fcr0, sizeof(unsigned int)); + + return err; +} + +static inline int refill_fp_context(struct sigcontext *sc) +{ + int err = 0; + + if (verify_area(VERIFY_READ, sc, sizeof(*sc))) + return -EFAULT; + err |= __copy_from_user(¤t->thread.fpu.hard.fp_regs[0], + &sc->sc_fpregs[0], NUM_FPU_REGS * sizeof(unsigned long)); + err |= __copy_from_user(¤t->thread.fpu.hard.control, &sc->sc_fpc_csr, + sizeof(unsigned int)); + return err; +} + /* * Atomically swap in the new signal mask, and wait for a signal. */ @@ -211,8 +240,12 @@ err |= __get_user(owned_fp, &sc->sc_ownedfp); if (owned_fp) { - err |= restore_fp_context(sc); - last_task_used_math = current; + if (IS_FPU_OWNER()) { + CLEAR_FPU_OWNER(); + regs->cp0_status &= ~ST0_CU1; + } + current->used_math = 1; + err |= refill_fp_context(sc); } return err; @@ -237,7 +270,10 @@ { struct sigframe *frame; sigset_t blocked; + +#if DEBUG_MIPS64 printk("%s called.\n", __FUNCTION__); +#endif frame = (struct sigframe *) regs.regs[29]; if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) @@ -314,11 +350,9 @@ static int inline setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) { - int owned_fp; int err = 0; err |= __put_user(regs->cp0_epc, &sc->sc_pc); - err |= __put_user(regs->cp0_status, &sc->sc_status); #define save_gp_reg(i) { \ err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \ @@ -339,16 +373,19 @@ err |= __put_user(regs->cp0_cause, &sc->sc_cause); err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); - owned_fp = (current == last_task_used_math); - err |= __put_user(owned_fp, &sc->sc_ownedfp); - if (current->used_math) { /* fp is active. */ - set_cp0_status(ST0_CU1, ST0_CU1); - err |= save_fp_context(sc); - last_task_used_math = NULL; - regs->cp0_status &= ~ST0_CU1; + if (IS_FPU_OWNER()) { + lazy_fpu_switch(current, 0); + CLEAR_FPU_OWNER(); + regs->cp0_status &= ~ST0_CU1; + } + err |= __put_user(1, &sc->sc_ownedfp); + err |= store_fp_context(sc); current->used_math = 0; + } else { + err |= __put_user(0, &sc->sc_ownedfp); } + err |= __put_user(regs->cp0_status, &sc->sc_status); return err; } @@ -390,10 +427,10 @@ /* * Set up the return code ... * - * li v0, __NR_sigreturn + * li v0, __NR_Linux32_sigreturn * syscall */ - err |= __put_user(0x24020000 + __NR_sigreturn, + err |= __put_user(0x24020000 + __NR_Linux32_sigreturn, frame->sf_code + 0); err |= __put_user(0x0000000c , frame->sf_code + 1); @@ -453,10 +490,10 @@ /* * Set up the return code ... * - * li v0, __NR_sigreturn + * li v0, __NR_Linux32_sigreturn * syscall */ - err |= __put_user(0x24020000 + __NR_sigreturn, + err |= __put_user(0x24020000 + __NR_Linux32_sigreturn, frame->rs_code + 0); err |= __put_user(0x0000000c , frame->rs_code + 1); @@ -555,7 +592,10 @@ { struct k_sigaction *ka; siginfo_t info; + +#if DEBUG_MIPS64 printk("%s: delivering signal.\n", current->comm); +#endif if (!oldset) oldset = ¤t->blocked; @@ -656,7 +696,9 @@ if (regs->regs[0]) syscall_restart(regs, ka); /* Whee! Actually deliver the signal. */ +#if DEBUG_MIPS64 printk("%s: delivering signal.\n", __FUNCTION__); +#endif handle_signal(signr, ka, &info, oldset, regs); return 1; } @@ -674,6 +716,25 @@ regs->cp0_epc -= 8; } } + return 0; +} + +extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set, + old_sigset_t *oset); + +asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set, + old_sigset_t32 *oset) +{ + old_sigset_t s; + int ret; + mm_segment_t old_fs = get_fs(); + + if (set && get_user (s, set)) return -EFAULT; + set_fs (KERNEL_DS); + ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL); + set_fs (old_fs); + if (ret) return ret; + if (oset && put_user (s, oset)) return -EFAULT; return 0; } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/smp.c linux/arch/mips64/kernel/smp.c --- v2.3.99-pre8/linux/arch/mips64/kernel/smp.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/kernel/smp.c Sat May 13 08:30:17 2000 @@ -0,0 +1,258 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_SGI_IP27 + +#include +#include +#include +#include +#include + +#define DORESCHED 0xab +#define DOCALL 0xbc + +#define IRQ_TO_SWLEVEL(i) i + 7 /* Delete this from here */ + +static void sendintr(int destid, unsigned char status) +{ + int irq; + +#if (CPUS_PER_NODE == 2) + switch (status) { + case DORESCHED: irq = CPU_RESCHED_A_IRQ; break; + case DOCALL: irq = CPU_CALL_A_IRQ; break; + default: panic("sendintr"); + } + irq += cputoslice(destid); + + /* + * Convert the compact hub number to the NASID to get the correct + * part of the address space. Then set the interrupt bit associated + * with the CPU we want to send the interrupt to. + */ + REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cputocnode(destid)), + IRQ_TO_SWLEVEL(irq)); +#else + << Bomb! Must redefine this for more than 2 CPUS. >> +#endif +} + +#endif /* CONFIG_SGI_IP27 */ + +/* The 'big kernel lock' */ +spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED; +int smp_threads_ready = 0; /* Not used */ +atomic_t smp_commenced = ATOMIC_INIT(0); +struct cpuinfo_mips cpu_data[NR_CPUS]; +int smp_num_cpus; /* Number that came online. */ +int __cpu_number_map[NR_CPUS]; +int __cpu_logical_map[NR_CPUS]; +cycles_t cacheflush_time; + +static void smp_tune_scheduling (void) +{ +} + +void __init smp_boot_cpus(void) +{ + extern void allowboot(void); + extern int maxcpus; + + init_new_context(current, &init_mm); + global_irq_holder = 0; + current->processor = 0; + init_idle(); + smp_tune_scheduling(); + smp_num_cpus = maxcpus; + allowboot(); +} + +void __init smp_commence(void) +{ + wmb(); + atomic_set(&smp_commenced,1); +} + +static void stop_this_cpu(void *dummy) +{ + /* + * Remove this CPU + */ + for (;;); +} + +void smp_send_stop(void) +{ + smp_call_function(stop_this_cpu, NULL, 1, 0); + smp_num_cpus = 1; +} + +/* + * this function sends a 'reschedule' IPI to another CPU. + * it goes straight through and wastes no time serializing + * anything. Worst case is that we lose a reschedule ... + */ +void smp_send_reschedule(int cpu) +{ + sendintr(cpu, DORESCHED); +} + +/* Not really SMP stuff ... */ +int setup_profiling_timer(unsigned int multiplier) +{ + return 0; +} + +/* + * Run a function on all other CPUs. + * The function to run. This must be fast and non-blocking. + * An arbitrary pointer to pass to the function. + * If true, keep retrying until ready. + * If true, wait until function has completed on other CPUs. + * [RETURNS] 0 on success, else a negative status code. + * + * Does not return until remote CPUs are nearly ready to execute + * or are or have executed. + */ +static volatile struct call_data_struct { + void (*func) (void *info); + void *info; + atomic_t started; + atomic_t finished; + int wait; +} *call_data = NULL; + +int smp_call_function (void (*func) (void *info), void *info, int retry, + int wait) +{ + struct call_data_struct data; + int i, cpus = smp_num_cpus-1; + static spinlock_t lock = SPIN_LOCK_UNLOCKED; + + if (cpus == 0) + return 0; + + data.func = func; + data.info = info; + atomic_set(&data.started, 0); + data.wait = wait; + if (wait) + atomic_set(&data.finished, 0); + + spin_lock_bh(&lock); + call_data = &data; + /* Send a message to all other CPUs and wait for them to respond */ + for (i = 0; i < smp_num_cpus; i++) + if (smp_processor_id() != i) + sendintr(i, DOCALL); + + /* Wait for response */ + /* FIXME: lock-up detection, backtrace on lock-up */ + while (atomic_read(&data.started) != cpus) + barrier(); + + if (wait) + while (atomic_read(&data.finished) != cpus) + barrier(); + spin_unlock_bh(&lock); + return 0; +} + +void smp_call_function_interrupt(void) +{ + void (*func) (void *info) = call_data->func; + void *info = call_data->info; + int wait = call_data->wait; + + /* + * Notify initiating CPU that I've grabbed the data and am + * about to execute the function. + */ + atomic_inc(&call_data->started); + + /* + * At this point the info structure may be out of scope unless wait==1. + */ + (*func)(info); + if (wait) + atomic_inc(&call_data->finished); +} + + +static void flush_tlb_all_ipi(void *info) +{ + _flush_tlb_all(); +} + +void flush_tlb_all(void) +{ + smp_call_function(flush_tlb_all_ipi, 0, 1, 1); + _flush_tlb_all(); +} + +static void flush_tlb_mm_ipi(void *mm) +{ + _flush_tlb_mm((struct mm_struct *)mm); +} + +void flush_tlb_mm(struct mm_struct *mm) +{ + smp_call_function(flush_tlb_mm_ipi, (void *)mm, 1, 1); + _flush_tlb_mm(mm); +} + +struct flush_tlb_data { + struct mm_struct *mm; + struct vm_area_struct *vma; + unsigned long addr1; + unsigned long addr2; +}; + +static void flush_tlb_range_ipi(void *info) +{ + struct flush_tlb_data *fd = (struct flush_tlb_data *)info; + + _flush_tlb_range(fd->mm, fd->addr1, fd->addr2); +} + +void flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) +{ + struct flush_tlb_data fd; + + fd.mm = mm; + fd.addr1 = start; + fd.addr2 = end; + smp_call_function(flush_tlb_range_ipi, (void *)&fd, 1, 1); + _flush_tlb_range(mm, start, end); +} + +static void flush_tlb_page_ipi(void *info) +{ + struct flush_tlb_data *fd = (struct flush_tlb_data *)info; + + _flush_tlb_page(fd->vma, fd->addr1); +} + +void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + struct flush_tlb_data fd; + + fd.vma = vma; + fd.addr1 = page; + smp_call_function(flush_tlb_page_ipi, (void *)&fd, 1, 1); + _flush_tlb_page(vma, page); +} + diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/softfp.S linux/arch/mips64/kernel/softfp.S --- v2.3.99-pre8/linux/arch/mips64/kernel/softfp.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/softfp.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: softfp.S,v 1.1 1999/12/04 03:59:00 ralf Exp $ +/* $Id: softfp.S,v 1.2 2000/03/21 23:50:42 ulfc Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -148,7 +148,8 @@ insn: LOCK_KERNEL; \ la a1, 8f; \ TEXT(#insn); \ - la a1, nosim; \ + la a0, nosim; \ + jal printk; \ UNLOCK_KERNEL; \ j done @@ -165,9 +166,9 @@ .cpload $25 .set reorder - subu sp, 16 + dsubu sp, 16 .cprestore 20 - sw ra, 16(sp) + sd ra, 0(sp) /* For now we assume that we get the opcode to simulate passed in as an argument. */ @@ -178,9 +179,9 @@ */ la ta1, lowtab andi ta2, ta0, 0x3f - sll ta2, ta2, 2 - addu ta1, ta2 - lw ta1, (ta1) + sll ta2, ta2, 3 + daddu ta1, ta2 + ld ta1, (ta1) jr ta1 END(simfp) @@ -189,17 +190,17 @@ * can keep the jump table significantly shorter. */ #define FMT_switch(insn,opc,temp0,temp1) \ -insn: srl temp0, opc, 19; \ +insn: srl temp0, opc, 18; \ andi temp0, 0x1c; \ la temp1, insn ## .tab; \ - addu temp0, temp1; \ - lw temp0, (temp0); \ + daddu temp0, temp1; \ + ld temp0, (temp0); \ jr temp0; \ \ .data; \ insn ## .tab: \ - .word insn ## .s, insn ## .d, unimp, unimp; \ - .word insn ## .w, insn ## .l, unimp, unimp; \ + .dword insn ## .s, insn ## .d, unimp, unimp; \ + .dword insn ## .w, insn ## .l, unimp, unimp; \ .previous BITCH(add) @@ -293,8 +294,8 @@ full fp simulation. */ /* Done, return. */ - lw ra, 16(sp) - addu sp, 16 + ld ra, 0(sp) + daddu sp, 16 jr ra /* Convert a double fp to a fixed point integer. */ @@ -378,8 +379,8 @@ jal s_put_fpreg /* Done, return. */ - lw ra, 16(sp) - addu sp, 16 + ld ra, 0(sp) + daddu sp, 16 jr ra cvt.w.w = unimp # undefined result @@ -410,11 +411,9 @@ /* Get the single precission register which's number is in ta1. */ s_get_fpreg: .set noat - sll AT, ta1, 2 sll ta1, 3 - addu ta1, AT la AT, 1f - addu AT, ta1 + daddu AT, ta1 jr AT .set at @@ -489,11 +488,9 @@ */ s_put_fpreg: .set noat - sll AT, ta1, 2 sll ta1, 3 - addu ta1, AT la AT, 1f - addu AT, ta1 + daddu AT, ta1 jr AT .set at @@ -565,9 +562,11 @@ /* Get the double precission register which's number is in ta1 into ta1/ta2. */ d_get_fpreg: .set noat - sll ta1, 3 + sll AT, ta1, 1 + sll ta1, 2 + daddu ta1, AT la AT, 1f - addu AT, ta1 + daddu AT, ta1 jr AT .set at @@ -624,16 +623,16 @@ * Send an invalid operation exception. */ invalid: - lw ra, 16(sp) - addu sp, 16 + ld ra, 0(sp) + daddu sp, 16 jr ra /* * Done, just skip over the current instruction */ done: - lw ra, 16(sp) - addu sp, 16 + ld ra, 0(sp) + daddu sp, 16 jr ra unimp: @@ -641,7 +640,7 @@ on new, yet unsupported CPU types or when the faulting instruction is being executed for cache but has been overwritten in memory. */ LOCK_KERNEL - move a0, ta0 + move a1, ta0 PRINT(KERN_DEBUG "FP support: unknown fp op %08lx, ") PRINT("please mail to ralf@gnu.org.\n") UNLOCK_KERNEL @@ -650,19 +649,19 @@ move a1, $28 jal force_sig - lw ra, 16(sp) - addu sp, 16 + ld ra, 0(sp) + daddu sp, 16 jr ra /* * Jump table for the lowest 6 bits of a cp1 instruction. */ .data -lowtab: .word add, sub, mul, div, sqrt, abs, mov, neg - .word round.l,trunc.l,ceil.l,floor.l,round.w,trunc.w,ceil.w,floor.w - .word unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp - .word unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp - .word cvt.s, cvt.d, unimp, unimp, cvt.w, cvt.l, unimp, unimp - .word unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp - .word c.f, c.un, c.eq, c.ueq, c.olt, c.ult, c.ole, c.ule - .word c.sf, c.ngle,c.seq, c.ngl, c.lt, c.nge, c.le, c.ngt +lowtab: .dword add, sub, mul, div, sqrt, abs, mov, neg + .dword round.l,trunc.l,ceil.l,floor.l,round.w,trunc.w,ceil.w,floor.w + .dword unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp + .dword unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp + .dword cvt.s, cvt.d, unimp, unimp, cvt.w, cvt.l, unimp, unimp + .dword unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp + .dword c.f, c.un, c.eq, c.ueq, c.olt, c.ult, c.ole, c.ule + .dword c.sf, c.ngle,c.seq, c.ngl, c.lt, c.nge, c.le, c.ngt diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/syscall.c linux/arch/mips64/kernel/syscall.c --- v2.3.99-pre8/linux/arch/mips64/kernel/syscall.c Thu Mar 2 14:36:22 2000 +++ linux/arch/mips64/kernel/syscall.c Sat May 13 08:30:17 2000 @@ -108,7 +108,6 @@ int error; char * filename; - lock_kernel(); filename = getname((char *) (long)regs.regs[4]); error = PTR_ERR(filename); if (IS_ERR(filename)) @@ -118,7 +117,6 @@ putname(filename); out: - unlock_kernel(); return error; } @@ -322,4 +320,11 @@ asmlinkage void bad_stack(void) { do_exit(SIGSEGV); +} + +asmlinkage int sys_pause(void) +{ + current->state = TASK_INTERRUPTIBLE; + schedule(); + return -ERESTARTNOHAND; } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/traps.c linux/arch/mips64/kernel/traps.c --- v2.3.99-pre8/linux/arch/mips64/kernel/traps.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/traps.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.5 2000/02/24 00:12:41 ralf Exp $ +/* $Id: traps.c,v 1.4 2000/01/20 23:50:27 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -328,8 +328,9 @@ void do_ri(struct pt_regs *regs) { lock_kernel(); - printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n", - current->comm, current->pid, regs->cp0_epc, regs->regs[31]); + printk("Cpu%d[%s:%ld] Illegal instruction at %08lx ra=%08lx\n", + smp_processor_id(), current->comm, current->pid, regs->cp0_epc, + regs->regs[31]); unlock_kernel(); if (compute_return_epc(regs)) return; @@ -345,16 +346,27 @@ goto bad_cid; regs->cp0_status |= ST0_CU1; +#ifndef CONFIG_SMP if (last_task_used_math == current) return; if (current->used_math) { /* Using the FPU again. */ - lazy_fpu_switch(last_task_used_math); + lazy_fpu_switch(last_task_used_math, current); } else { /* First time FPU user. */ + lazy_fpu_switch(last_task_used_math, 0); init_fpu(); current->used_math = 1; } last_task_used_math = current; +#else + if (current->used_math) { + lazy_fpu_switch(0, current); + } else { + init_fpu(); + current->used_math = 1; + } + current->flags |= PF_USEDFPU; +#endif return; bad_cid: @@ -446,7 +458,6 @@ mips4_available = 1; set_cp0_status(ST0_XX, ST0_XX); } - mips4_available = 0; } static inline void go_64(void) @@ -561,5 +572,4 @@ atomic_inc(&init_mm.mm_count); /* XXX UP? */ current->active_mm = &init_mm; - current_pgd = init_mm.pgd; } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/unaligned.c linux/arch/mips64/kernel/unaligned.c --- v2.3.99-pre8/linux/arch/mips64/kernel/unaligned.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/kernel/unaligned.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: unaligned.c,v 1.2 2000/01/17 23:32:46 ralf Exp $ +/* $Id: unaligned.c,v 1.2 1999/11/23 17:12:50 ralf Exp $ * * Handle unaligned accesses by emulation. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/Makefile linux/arch/mips64/lib/Makefile --- v2.3.99-pre8/linux/arch/mips64/lib/Makefile Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/Makefile Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.2 1999/12/04 03:59:00 ralf Exp $ +# $Id: Makefile,v 1.2 1999/11/19 20:35:22 ralf Exp $ # # Makefile for MIPS-specific library files.. # diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/csum_partial.S linux/arch/mips64/lib/csum_partial.S --- v2.3.99-pre8/linux/arch/mips64/lib/csum_partial.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/csum_partial.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: csum_partial.S,v 1.2 1999/12/04 03:59:00 ralf Exp $ +/* $Id: csum_partial.S,v 1.1 1999/08/21 21:43:00 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/csum_partial_copy.c linux/arch/mips64/lib/csum_partial_copy.c --- v2.3.99-pre8/linux/arch/mips64/lib/csum_partial_copy.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/csum_partial_copy.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: csum_partial_copy.c,v 1.3 2000/02/05 06:47:09 ralf Exp $ +/* $Id: csum_partial_copy.c,v 1.2 1999/12/04 03:59:00 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/floppy-no.c linux/arch/mips64/lib/floppy-no.c --- v2.3.99-pre8/linux/arch/mips64/lib/floppy-no.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/floppy-no.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: floppy-no.c,v 1.2 1999/12/04 03:59:00 ralf Exp $ +/* $Id: floppy-no.c,v 1.1 1999/08/21 21:43:00 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/floppy-std.c linux/arch/mips64/lib/floppy-std.c --- v2.3.99-pre8/linux/arch/mips64/lib/floppy-std.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/floppy-std.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: floppy-std.c,v 1.2 1999/12/04 03:59:00 ralf Exp $ +/* $Id: floppy-std.c,v 1.1 1999/08/21 21:43:00 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/ide-no.c linux/arch/mips64/lib/ide-no.c --- v2.3.99-pre8/linux/arch/mips64/lib/ide-no.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/ide-no.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ide-no.c,v 1.2 1999/12/04 03:59:00 ralf Exp $ +/* $Id: ide-no.c,v 1.1 1999/08/21 21:43:00 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/ide-std.c linux/arch/mips64/lib/ide-std.c --- v2.3.99-pre8/linux/arch/mips64/lib/ide-std.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/ide-std.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ide-std.c,v 1.2 1999/12/04 03:59:00 ralf Exp $ +/* $Id: ide-std.c,v 1.1 1999/08/21 21:43:00 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/kbd-no.c linux/arch/mips64/lib/kbd-no.c --- v2.3.99-pre8/linux/arch/mips64/lib/kbd-no.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/kbd-no.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: kbd-no.c,v 1.2 1999/12/04 03:59:00 ralf Exp $ +/* $Id: kbd-no.c,v 1.1 1999/08/21 21:43:00 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/kbd-std.c linux/arch/mips64/lib/kbd-std.c --- v2.3.99-pre8/linux/arch/mips64/lib/kbd-std.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/kbd-std.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: kbd-std.c,v 1.2 1999/12/04 03:59:00 ralf Exp $ +/* $Id: kbd-std.c,v 1.1 1999/08/21 21:43:01 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/memcpy.S linux/arch/mips64/lib/memcpy.S --- v2.3.99-pre8/linux/arch/mips64/lib/memcpy.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/memcpy.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: memcpy.S,v 1.4 2000/01/27 01:05:24 ralf Exp $ +/* $Id: memcpy.S,v 1.2 1999/10/19 20:51:51 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/memset.S linux/arch/mips64/lib/memset.S --- v2.3.99-pre8/linux/arch/mips64/lib/memset.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/memset.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: memset.S,v 1.3 2000/01/16 01:37:19 ralf Exp $ +/* $Id: memset.S,v 1.3 2000/01/15 23:48:55 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/rtc-no.c linux/arch/mips64/lib/rtc-no.c --- v2.3.99-pre8/linux/arch/mips64/lib/rtc-no.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/rtc-no.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: rtc-no.c,v 1.2 1999/12/04 03:59:00 ralf Exp $ +/* $Id: rtc-no.c,v 1.1 1999/08/21 21:43:01 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/rtc-std.c linux/arch/mips64/lib/rtc-std.c --- v2.3.99-pre8/linux/arch/mips64/lib/rtc-std.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/rtc-std.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: rtc-std.c,v 1.2 1999/12/04 03:59:00 ralf Exp $ +/* $Id: rtc-std.c,v 1.1 1999/08/21 21:43:01 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/strlen_user.S linux/arch/mips64/lib/strlen_user.S --- v2.3.99-pre8/linux/arch/mips64/lib/strlen_user.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/strlen_user.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: strlen_user.S,v 1.3 2000/01/17 23:32:46 ralf Exp $ +/* $Id: strlen_user.S,v 1.2 1999/11/19 20:35:22 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/strncpy_user.S linux/arch/mips64/lib/strncpy_user.S --- v2.3.99-pre8/linux/arch/mips64/lib/strncpy_user.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/strncpy_user.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: strncpy_user.S,v 1.3 2000/01/17 23:32:46 ralf Exp $ +/* $Id: strncpy_user.S,v 1.2 1999/11/19 20:35:23 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/strnlen_user.S linux/arch/mips64/lib/strnlen_user.S --- v2.3.99-pre8/linux/arch/mips64/lib/strnlen_user.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/strnlen_user.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: strnlen_user.S,v 1.1 1999/12/04 03:59:00 ralf Exp $ +/* $Id: strnlen_user.S,v 1.1 1999/11/19 20:35:23 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/watch.S linux/arch/mips64/lib/watch.S --- v2.3.99-pre8/linux/arch/mips64/lib/watch.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/lib/watch.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: watch.S,v 1.2 1999/12/04 03:59:00 ralf Exp $ +/* $Id: watch.S,v 1.1 1999/08/21 21:43:01 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/Makefile linux/arch/mips64/mm/Makefile --- v2.3.99-pre8/linux/arch/mips64/mm/Makefile Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/mm/Makefile Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.5 2000/02/24 00:12:41 ralf Exp $ +# $Id: Makefile,v 1.4 2000/01/17 23:32:46 ralf Exp $ # # Makefile for the Linux/MIPS-specific parts of the memory manager. # diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/andes.c linux/arch/mips64/mm/andes.c --- v2.3.99-pre8/linux/arch/mips64/mm/andes.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/mm/andes.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: andes.c,v 1.6 2000/02/24 00:12:41 ralf Exp $ +/* $Id: andes.c,v 1.7 2000/03/13 22:43:25 kanoj Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -91,7 +91,7 @@ static void andes_flush_cache_mm(struct mm_struct *mm) { - if (mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -103,7 +103,7 @@ andes_flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - if (mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { unsigned long flags; #ifdef DEBUG_CACHE @@ -129,7 +129,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if (mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; #ifdef DEBUG_CACHE @@ -244,17 +244,17 @@ static void andes_flush_tlb_mm(struct mm_struct *mm) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { unsigned long flags; #ifdef DEBUG_TLB printk("[tlbmm<%d>]", mm->context); #endif - save_and_cli(flags); - get_new_mmu_context(mm, asid_cache); + __save_and_cli(flags); + get_new_cpu_mmu_context(mm, smp_processor_id()); if(mm == current->mm) - set_entryhi(mm->context & 0xff); - restore_flags(flags); + set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & 0xff); + __restore_flags(flags); } } @@ -262,7 +262,7 @@ andes_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { unsigned long flags; int size; @@ -270,12 +270,12 @@ printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), start, end); #endif - save_and_cli(flags); + __save_and_cli(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; if(size <= NTLB_ENTRIES_HALF) { int oldpid = (get_entryhi() & 0xff); - int newpid = (mm->context & 0xff); + int newpid = (CPU_CONTEXT(smp_processor_id(), mm) & 0xff); start &= (PAGE_MASK << 1); end += ((PAGE_SIZE << 1) - 1); @@ -300,9 +300,10 @@ } set_entryhi(oldpid); } else { - get_new_mmu_context(mm, asid_cache); + get_new_cpu_mmu_context(mm, smp_processor_id()); if(mm == current->mm) - set_entryhi(mm->context & 0xff); + set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & + 0xff); } __restore_flags(flags); } @@ -311,16 +312,16 @@ static void andes_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { - if(vma->vm_mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) != 0) { unsigned long flags; int oldpid, newpid, idx; #ifdef DEBUG_TLB printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); #endif - newpid = (vma->vm_mm->context & 0xff); + newpid = (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff); page &= (PAGE_MASK << 1); - save_and_cli(flags); + __save_and_cli(flags); oldpid = (get_entryhi() & 0xff); set_entryhi(page | newpid); BARRIER; @@ -338,7 +339,7 @@ finish: BARRIER; set_entryhi(oldpid); - restore_flags(flags); + __restore_flags(flags); } } @@ -354,17 +355,16 @@ pte_t *ptep; int idx, pid; + __save_and_cli(flags); pid = get_entryhi() & 0xff; -#ifdef DEBUG_TLB - if((pid != (vma->vm_mm->context & 0xff)) || - (vma->vm_mm->context == 0)) { - printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n", - (int) (vma->vm_mm->context & 0xff), pid); + if((pid != (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff)) || + (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) == 0)) { + printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d + tlbpid=%d\n", (int) (CPU_CONTEXT(smp_processor_id(), + vma->vm_mm) & 0xff), pid); } -#endif - __save_and_cli(flags); address &= (PAGE_MASK << 1); set_entryhi(address | (pid)); pgdp = pgd_offset(vma->vm_mm, address); @@ -398,6 +398,7 @@ static void andes_show_regs(struct pt_regs *regs) { + printk("Cpu %d\n", smp_processor_id()); /* Saved main processor registers. */ printk("$0 : %016lx %016lx %016lx %016lx\n", 0UL, regs->regs[1], regs->regs[2], regs->regs[3]); @@ -469,7 +470,7 @@ write_32bit_cp0_register(CP0_PAGEMASK, PM_4K); /* From this point on the ARC firmware is dead. */ - flush_tlb_all(); + _flush_tlb_all(); /* Did I tell you that ARC SUCKS? */ } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/extable.c linux/arch/mips64/mm/extable.c --- v2.3.99-pre8/linux/arch/mips64/mm/extable.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/mm/extable.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: extable.c,v 1.2 1999/12/04 03:59:00 ralf Exp $ +/* $Id: extable.c,v 1.2 1999/11/23 17:12:50 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/fault.c linux/arch/mips64/mm/fault.c --- v2.3.99-pre8/linux/arch/mips64/mm/fault.c Wed Apr 26 16:34:07 2000 +++ linux/arch/mips64/mm/fault.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.6 2000/02/18 00:24:31 ralf Exp $ +/* $Id: fault.c,v 1.7 2000/03/13 22:43:25 kanoj Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -27,18 +27,36 @@ #include #include #include +#include #define development_version (LINUX_VERSION_CODE & 0x100) extern void die(char *, struct pt_regs *, unsigned long write); -unsigned long asid_cache; - /* * Macro for exception fixup code to access integer registers. */ #define dpf_reg(r) (regs->regs[r]) +asmlinkage void +dodebug(abi64_no_regargs, struct pt_regs regs) +{ + printk("Got syscall %d, cpu %d proc %s:%d epc 0x%lx\n", regs.regs[2], smp_processor_id(), current->comm, current->pid, regs.cp0_epc); +} + +asmlinkage void +dodebug2(abi64_no_regargs, struct pt_regs regs) +{ + unsigned long retaddr; + + __asm__ __volatile__( + ".set noreorder\n\t" + "add %0,$0,$31\n\t" + ".set reorder" + : "=r" (retaddr)); + printk("Got exception 0x%lx at 0x%lx\n", retaddr, regs.cp0_epc); +} + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate @@ -59,9 +77,9 @@ */ if (in_interrupt() || mm == &init_mm) goto no_context; -#if 0 - printk("[%s:%d:%08lx:%ld:%08lx]\n", current->comm, current->pid, - address, write, regs->cp0_epc); +#if DEBUG_MIPS64 + printk("Cpu%d[%s:%d:%08lx:%ld:%08lx]\n", smp_processor_id(), current->comm, + current->pid, address, write, regs->cp0_epc); #endif down(&mm->mmap_sem); vma = find_vma(mm, address); @@ -93,12 +111,17 @@ * make sure we exit gracefully rather than endlessly redo * the fault. */ - { - int fault = handle_mm_fault(mm, vma, address, write); - if (fault < 0) - goto out_of_memory; - if (!fault) - goto do_sigbus; + switch (handle_mm_fault(mm, vma, address, write)) { + case 1: + tsk->min_flt++; + break; + case 2: + tsk->maj_flt++; + break; + case 0: + goto do_sigbus; + default: + goto out_of_memory; } up(&mm->mmap_sem); @@ -150,10 +173,9 @@ * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ - printk(KERN_ALERT "Unable to handle kernel paging request at virtual " + printk(KERN_ALERT "Cpu %d Unable to handle kernel paging request at " "address %08lx, epc == %08lx, ra == %08lx\n", - address, regs->cp0_epc, regs->regs[31]); -while(1); + smp_processor_id(), address, regs->cp0_epc, regs->regs[31]); die("Oops", regs, write); do_exit(SIGKILL); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/init.c linux/arch/mips64/mm/init.c --- v2.3.99-pre8/linux/arch/mips64/mm/init.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/mm/init.c Sat May 13 08:30:17 2000 @@ -87,6 +87,8 @@ if (ret) { init = pgd_offset(&init_mm, 0); pgd_init((unsigned long)ret); + memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, + (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); } return ret; } @@ -250,7 +252,7 @@ bp = pte_val(BAD_PAGE); p = (unsigned long *) page; - end = p + PTRS_PER_PTE; + end = p + (2 * PTRS_PER_PTE); while (p < end) { p[0] = p[1] = p[2] = p[3] = @@ -278,7 +280,7 @@ unsigned long page; page = (unsigned long) invalid_pmd_table; - pte_init(page); + pmd_init(page); return (pmd_t *) page; } @@ -345,8 +347,8 @@ /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); - pgd_init((unsigned long)swapper_pg_dir + PAGE_SIZE / 2); pmd_init((unsigned long)invalid_pmd_table); + memset((void *)invalid_pte_table, 0, sizeof(pte_t) * 2 * PTRS_PER_PTE); max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; low = max_low_pfn; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/loadmmu.c linux/arch/mips64/mm/loadmmu.c --- v2.3.99-pre8/linux/arch/mips64/mm/loadmmu.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/mm/loadmmu.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: loadmmu.c,v 1.6 2000/02/24 00:12:41 ralf Exp $ +/* $Id: loadmmu.c,v 1.5 2000/01/27 01:05:24 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/r4xx0.c linux/arch/mips64/mm/r4xx0.c --- v2.3.99-pre8/linux/arch/mips64/mm/r4xx0.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/mm/r4xx0.c Sat May 13 08:30:17 2000 @@ -784,7 +784,7 @@ struct vm_area_struct *vma; unsigned long flags; - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; start &= PAGE_MASK; @@ -793,7 +793,8 @@ #endif vma = find_vma(mm, start); if(vma) { - if(mm->context != current->mm->context) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { r4k_flush_cache_all_s16d16i16(); } else { pgd_t *pgd; @@ -822,7 +823,7 @@ struct vm_area_struct *vma; unsigned long flags; - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; start &= PAGE_MASK; @@ -831,7 +832,8 @@ #endif vma = find_vma(mm, start); if(vma) { - if(mm->context != current->mm->context) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { r4k_flush_cache_all_s32d16i16(); } else { pgd_t *pgd; @@ -860,7 +862,7 @@ struct vm_area_struct *vma; unsigned long flags; - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; start &= PAGE_MASK; @@ -869,7 +871,8 @@ #endif vma = find_vma(mm, start); if(vma) { - if(mm->context != current->mm->context) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { r4k_flush_cache_all_s64d16i16(); } else { pgd_t *pgd; @@ -898,7 +901,7 @@ struct vm_area_struct *vma; unsigned long flags; - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; start &= PAGE_MASK; @@ -907,7 +910,8 @@ #endif vma = find_vma(mm, start); if(vma) { - if(mm->context != current->mm->context) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { r4k_flush_cache_all_s128d16i16(); } else { pgd_t *pgd; @@ -936,7 +940,7 @@ struct vm_area_struct *vma; unsigned long flags; - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; start &= PAGE_MASK; @@ -945,7 +949,8 @@ #endif vma = find_vma(mm, start); if(vma) { - if(mm->context != current->mm->context) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { r4k_flush_cache_all_s32d32i32(); } else { pgd_t *pgd; @@ -974,7 +979,7 @@ struct vm_area_struct *vma; unsigned long flags; - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; start &= PAGE_MASK; @@ -983,7 +988,8 @@ #endif vma = find_vma(mm, start); if(vma) { - if(mm->context != current->mm->context) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { r4k_flush_cache_all_s64d32i32(); } else { pgd_t *pgd; @@ -1012,7 +1018,7 @@ struct vm_area_struct *vma; unsigned long flags; - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { return; start &= PAGE_MASK; @@ -1021,7 +1027,8 @@ #endif vma = find_vma(mm, start); if(vma) { - if(mm->context != current->mm->context) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { r4k_flush_cache_all_s128d32i32(); } else { pgd_t *pgd; @@ -1047,7 +1054,7 @@ r4k_flush_cache_range_d16i16(struct mm_struct *mm, unsigned long start, unsigned long end) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { unsigned long flags; #ifdef DEBUG_CACHE @@ -1063,7 +1070,7 @@ r4k_flush_cache_range_d32i32(struct mm_struct *mm, unsigned long start, unsigned long end) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { unsigned long flags; #ifdef DEBUG_CACHE @@ -1082,7 +1089,7 @@ */ static void r4k_flush_cache_mm_s16d16i16(struct mm_struct *mm) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1092,7 +1099,7 @@ static void r4k_flush_cache_mm_s32d16i16(struct mm_struct *mm) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1102,7 +1109,7 @@ static void r4k_flush_cache_mm_s64d16i16(struct mm_struct *mm) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1112,7 +1119,7 @@ static void r4k_flush_cache_mm_s128d16i16(struct mm_struct *mm) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1122,7 +1129,7 @@ static void r4k_flush_cache_mm_s32d32i32(struct mm_struct *mm) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1132,7 +1139,7 @@ static void r4k_flush_cache_mm_s64d32i32(struct mm_struct *mm) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1142,7 +1149,7 @@ static void r4k_flush_cache_mm_s128d32i32(struct mm_struct *mm) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1152,7 +1159,7 @@ static void r4k_flush_cache_mm_d16i16(struct mm_struct *mm) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1162,7 +1169,7 @@ static void r4k_flush_cache_mm_d32i32(struct mm_struct *mm) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { #ifdef DEBUG_CACHE printk("cmm[%d]", (int)mm->context); #endif @@ -1184,7 +1191,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; #ifdef DEBUG_CACHE @@ -1209,7 +1216,8 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm->context != current->mm->context) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ @@ -1238,7 +1246,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; #ifdef DEBUG_CACHE @@ -1262,7 +1270,8 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm->context != current->mm->context) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ @@ -1291,7 +1300,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; #ifdef DEBUG_CACHE @@ -1316,7 +1325,8 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm->context != current->mm->context) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ @@ -1345,7 +1355,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; #ifdef DEBUG_CACHE @@ -1370,7 +1380,8 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm->context != current->mm->context) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { /* * Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. @@ -1400,7 +1411,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; #ifdef DEBUG_CACHE @@ -1426,7 +1437,8 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm->context != current->mm->context) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { /* * Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. @@ -1456,7 +1468,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; #ifdef DEBUG_CACHE @@ -1482,7 +1494,8 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm->context != current->mm->context) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { /* * Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. @@ -1512,7 +1525,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; #ifdef DEBUG_CACHE @@ -1537,7 +1550,8 @@ * for every cache flush operation. So we do indexed flushes * in that case, which doesn't overly flush the cache too much. */ - if(mm->context != current->mm->context) { + if (CPU_CONTEXT(smp_processor_id(), mm) != + CPU_CONTEXT(smp_processor_id(), current->mm)) { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ @@ -1566,7 +1580,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; #ifdef DEBUG_CACHE @@ -1622,7 +1636,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; #ifdef DEBUG_CACHE @@ -1681,7 +1695,7 @@ * If ownes no valid ASID yet, cannot possibly have gotten * this page into the cache. */ - if(mm->context == 0) + if (CPU_CONTEXT(smp_processor_id(), mm) == 0) return; #ifdef DEBUG_CACHE @@ -2010,7 +2024,7 @@ printk("[tlball]"); #endif - save_and_cli(flags); + __save_and_cli(flags); /* Save old context and create impossible VPN2 value */ old_ctx = (get_entryhi() & 0xff); set_entryhi(KSEG0); @@ -2030,29 +2044,29 @@ } BARRIER; set_entryhi(old_ctx); - restore_flags(flags); + __restore_flags(flags); } static void r4k_flush_tlb_mm(struct mm_struct *mm) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { unsigned long flags; #ifdef DEBUG_TLB printk("[tlbmm<%d>]", mm->context); #endif - save_and_cli(flags); - get_new_mmu_context(mm, asid_cache); + __save_and_cli(flags); + get_new_cpu_mmu_context(mm, smp_processor_id()); if(mm == current->mm) - set_entryhi(mm->context & 0xff); - restore_flags(flags); + set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & 0xff); + __restore_flags(flags); } } static void r4k_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - if(mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { unsigned long flags; int size; @@ -2060,12 +2074,12 @@ printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), start, end); #endif - save_and_cli(flags); + __save_and_cli(flags); size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; size = (size + 1) >> 1; if(size <= NTLB_ENTRIES_HALF) { int oldpid = (get_entryhi() & 0xff); - int newpid = (mm->context & 0xff); + int newpid = (CPU_CONTEXT(smp_processor_id(), mm) & 0xff); start &= (PAGE_MASK << 1); end += ((PAGE_SIZE << 1) - 1); @@ -2090,9 +2104,10 @@ } set_entryhi(oldpid); } else { - get_new_mmu_context(mm, asid_cache); + get_new_cpu_mmu_context(mm, smp_processor_id()); if(mm == current->mm) - set_entryhi(mm->context & 0xff); + set_entryhi(CPU_CONTEXT(smp_processor_id(), + mm) & 0xff); } __restore_flags(flags); } @@ -2100,16 +2115,16 @@ static void r4k_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { - if(vma->vm_mm->context != 0) { + if (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) != 0) { unsigned long flags; int oldpid, newpid, idx; #ifdef DEBUG_TLB printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); #endif - newpid = (vma->vm_mm->context & 0xff); + newpid = (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff); page &= (PAGE_MASK << 1); - save_and_cli(flags); + __save_and_cli(flags); oldpid = (get_entryhi() & 0xff); set_entryhi(page | newpid); BARRIER; @@ -2127,7 +2142,7 @@ finish: BARRIER; set_entryhi(oldpid); - restore_flags(flags); + __restore_flags(flags); } } @@ -2150,16 +2165,18 @@ pte_t *ptep; int idx, pid; + __save_and_cli(flags); pid = (get_entryhi() & 0xff); #ifdef DEBUG_TLB - if((pid != (vma->vm_mm->context & 0xff)) || (vma->vm_mm->context == 0)) { - printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n", - (int) (vma->vm_mm->context & 0xff), pid); + if((pid != (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff)) || + (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) == 0)) { + printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d + tlbpid=%d\n", (int) (CPU_CONTEXT(smp_processor_id(), + vma->vm_mm) & 0xff), pid); } #endif - __save_and_cli(flags); address &= (PAGE_MASK << 1); set_entryhi(address | (pid)); pgdp = pgd_offset(vma->vm_mm, address); @@ -2538,5 +2555,5 @@ * be set for 4kb pages. */ write_32bit_cp0_register(CP0_PAGEMASK, PM_4K); - flush_tlb_all(); + _flush_tlb_all(); } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/umap.c linux/arch/mips64/mm/umap.c --- v2.3.99-pre8/linux/arch/mips64/mm/umap.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/mm/umap.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: umap.c,v 1.5 2000/02/04 07:40:24 ralf Exp $ +/* $Id: umap.c,v 1.4 2000/01/29 01:41:59 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/Makefile linux/arch/mips64/sgi-ip22/Makefile --- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/Makefile Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip22/Makefile Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.4 2000/01/21 22:34:03 ralf Exp $ +# $Id: Makefile,v 1.1 1999/08/20 21:13:33 ralf Exp $ # # Makefile for the SGI specific kernel interface routines # under Linux. diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-berr.c linux/arch/mips64/sgi-ip22/ip22-berr.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-berr.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip22/ip22-berr.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ip22-berr.c,v 1.2 2000/02/24 00:12:41 ralf Exp $ +/* $Id: ip22-berr.c,v 1.1 2000/01/21 22:34:03 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-hpc.c linux/arch/mips64/sgi-ip22/ip22-hpc.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-hpc.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip22/ip22-hpc.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ip22-hpc.c,v 1.2 1999/12/04 03:59:01 ralf Exp $ +/* $Id: ip22-hpc.c,v 1.2 1999/10/19 20:51:52 ralf Exp $ * * ip22-hpc.c: Routines for generic manipulation of the HPC controllers. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-int.c linux/arch/mips64/sgi-ip22/ip22-int.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-int.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip22/ip22-int.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ip22-int.c,v 1.4 2000/02/04 07:40:24 ralf Exp $ +/* $Id: ip22-int.c,v 1.5 2000/03/02 02:36:50 ralf Exp $ * * indy_int.c: Routines for generic manipulation of the INT[23] ASIC * found on INDY workstations.. @@ -37,6 +37,24 @@ #include #include +/* + * Linux has a controller-independent x86 interrupt architecture. + * every controller has a 'controller-template', that is used + * by the main code to do the right thing. Each driver-visible + * interrupt source is transparently wired to the apropriate + * controller. Thus drivers need not be aware of the + * interrupt-controller. + * + * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, + * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. + * (IO-APICs assumed to be messaging to Pentium local-APICs) + * + * the code is designed to be easily extended with new/different + * interrupt controllers, without having to do assembly magic. + */ + +irq_cpustat_t irq_stat [NR_CPUS]; + struct sgi_int2_regs *sgi_i2regs; struct sgi_int3_regs *sgi_i3regs; struct sgi_ioc_ints *ioc_icontrol; @@ -272,7 +290,7 @@ int do_random, cpu; cpu = smp_processor_id(); - irq_enter(cpu); + irq_enter(cpu, irq); kstat.irqs[0][irq]++; printk("Got irq %d, press a key.", irq); @@ -308,7 +326,7 @@ add_interrupt_randomness(irq); __cli(); } - irq_exit(cpu); + irq_exit(cpu, irq); /* unmasking and bottom half handling is done magically for us. */ } @@ -433,10 +451,10 @@ action = local_irq_action[irq]; } - irq_enter(cpu); + irq_enter(cpu, irq); kstat.irqs[0][irq + 16]++; action->handler(irq, action->dev_id, regs); - irq_exit(cpu); + irq_exit(cpu, irq); } void indy_local1_irqdispatch(struct pt_regs *regs) @@ -457,10 +475,10 @@ irq = lc1msk_to_irqnr[mask]; action = local_irq_action[irq]; } - irq_enter(cpu); + irq_enter(cpu, irq); kstat.irqs[0][irq + 24]++; action->handler(irq, action->dev_id, regs); - irq_exit(cpu); + irq_exit(cpu, irq); } void indy_buserror_irq(struct pt_regs *regs) @@ -468,13 +486,13 @@ int cpu = smp_processor_id(); int irq = 6; - irq_enter(cpu); + irq_enter(cpu, irq); kstat.irqs[0][irq]++; printk("Got a bus error IRQ, shouldn't happen yet\n"); show_regs(regs); printk("Spinning...\n"); while(1); - irq_exit(cpu); + irq_exit(cpu, irq); } /* Misc. crap just to keep the kernel linking... */ diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-irq.S linux/arch/mips64/sgi-ip22/ip22-irq.S --- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-irq.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip22/ip22-irq.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ip22-irq.S,v 1.2 1999/12/04 03:59:01 ralf Exp $ +/* $Id: ip22-irq.S,v 1.1 1999/08/20 21:13:33 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-mc.c linux/arch/mips64/sgi-ip22/ip22-mc.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-mc.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip22/ip22-mc.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ip22-mc.c,v 1.2 1999/12/04 03:59:01 ralf Exp $ +/* $Id: ip22-mc.c,v 1.2 1999/10/19 20:51:52 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-reset.c linux/arch/mips64/sgi-ip22/ip22-reset.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-reset.c Thu May 11 15:30:06 2000 +++ linux/arch/mips64/sgi-ip22/ip22-reset.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ip22-reset.c,v 1.3 1999/12/04 03:59:01 ralf Exp $ +/* $Id: ip22-reset.c,v 1.3 1999/10/08 21:07:51 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-rtc.c linux/arch/mips64/sgi-ip22/ip22-rtc.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-rtc.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip22/ip22-rtc.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ip22-rtc.c,v 1.2 1999/12/04 03:59:01 ralf Exp $ +/* $Id: ip22-rtc.c,v 1.1 1999/08/20 21:13:34 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-sc.c linux/arch/mips64/sgi-ip22/ip22-sc.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-sc.c Mon Mar 27 08:08:22 2000 +++ linux/arch/mips64/sgi-ip22/ip22-sc.c Sat May 13 08:30:17 2000 @@ -27,7 +27,6 @@ #define SC_SIZE 0x00080000 #define SC_LINE 32 #define CI_MASK (SC_SIZE - SC_LINE) -#define SC_ROUND(n) ((n) + SC_LINE - 1) #define SC_INDEX(n) ((n) & CI_MASK) static inline void indy_sc_wipe(unsigned long first, unsigned long last) @@ -53,9 +52,13 @@ #ifdef DEBUG_CACHE printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size); #endif + + if (!size) + return; + /* Which lines to flush? */ first_line = SC_INDEX(addr); - last_line = SC_INDEX(SC_ROUND(addr + size)); + last_line = SC_INDEX(addr + size - 1); __save_and_cli(flags); if (first_line <= last_line) { @@ -63,11 +66,8 @@ goto out; } - /* Cache index wrap around. Due to the way the buddy system works - this case should not happen. We're prepared to handle it, - though. */ - indy_sc_wipe(last_line, SC_SIZE); - indy_sc_wipe(0, first_line); + indy_sc_wipe(first_line, SC_SIZE - SC_LINE); + indy_sc_wipe(0, last_line); out: __restore_flags(flags); } @@ -159,7 +159,6 @@ void __init indy_sc_init(void) { -return; /* Not for now, debugging ... */ if (indy_sc_probe()) { indy_sc_enable(); bcops = &indy_sc_ops; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-setup.c linux/arch/mips64/sgi-ip22/ip22-setup.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-setup.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip22/ip22-setup.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ip22-setup.c,v 1.5 2000/01/27 01:05:24 ralf Exp $ +/* $Id: ip22-setup.c,v 1.4 1999/10/08 21:07:51 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-timer.c linux/arch/mips64/sgi-ip22/ip22-timer.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-timer.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip22/ip22-timer.c Sat May 13 08:30:17 2000 @@ -267,12 +267,12 @@ int cpu = smp_processor_id(); int irq = 4; - irq_enter(cpu); + irq_enter(cpu, irq); kstat.irqs[0][irq]++; printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n"); prom_getchar(); ArcEnterInteractiveMode(); - irq_exit(cpu); + irq_exit(cpu, irq); } void do_gettimeofday(struct timeval *tv) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/system.c linux/arch/mips64/sgi-ip22/system.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/system.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip22/system.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: system.c,v 1.3 1999/12/04 03:59:01 ralf Exp $ +/* $Id: system.c,v 1.3 1999/10/19 20:51:52 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/time.c linux/arch/mips64/sgi-ip22/time.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/time.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip22/time.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.2 1999/12/04 03:59:01 ralf Exp $ +/* $Id: time.c,v 1.1 1999/08/20 21:13:34 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/Makefile linux/arch/mips64/sgi-ip27/Makefile --- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/Makefile Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip27/Makefile Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.4 2000/02/18 00:24:31 ralf Exp $ +# $Id: Makefile,v 1.3 2000/02/04 08:41:40 kanoj Exp $ # # Makefile for the IP27 specific kernel interface routines under Linux. # @@ -11,6 +11,6 @@ L_TARGET = ip27.a L_OBJS = ip27-berr.o ip27-irq.o ip27-irq-glue.o ip27-klconfig.o \ ip27-memory.o ip27-pci.o ip27-pci-dma.o ip27-reset.o ip27-setup.o \ - ip27-timer.o ip27-init.o + ip27-timer.o ip27-init.o ip27-nmi.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/TODO linux/arch/mips64/sgi-ip27/TODO --- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/TODO Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip27/TODO Sat May 13 08:30:17 2000 @@ -4,8 +4,20 @@ 3. Need to figure out why address swaizzling is needed in inw/outw for Qlogic scsi controllers. 4. Need to integrate ip27-klconfig.c:find_lboard and -ip27-init.c:find_lbaord_real. +ip27-init.c:find_lbaord_real. DONE 5. Is it okay to set calias space on all nodes as 0, instead of 8k as in irix? 6. Investigate why things do not work without the setup_test() call being invoked on all nodes in ip27-memory.c. +7. Too many CLIs in the locore handlers : +For the low level handlers set up by set_except_vector(), +__tlb_refill_debug_tramp, __xtlb_refill_debug_tramp and cacheerror, +investigate whether the code should do CLI, STI or KMODE. +8. Too many do_page_faults invoked - investigate. +9. start_thread must turn off UX64 ... and define tlb_refill_debug. +10. Need a bad pmd table, bad pte table. __bad_pmd_table/__bad_pagetable +does not agree with pgd_bad/pmd_bad. +11. All intrs (ip27_do_irq handlers) are targetted at cpu A on the node. +This might need to change later. Only the timer intr is set up to be +received on both Cpu A and B. (ip27_do_irq()/bridge_startup()) +13. Cache flushing (specially the SMP version) has to be investigated. diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-berr.c linux/arch/mips64/sgi-ip27/ip27-berr.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-berr.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip27/ip27-berr.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ip27-berr.c,v 1.1 2000/01/20 23:50:27 ralf Exp $ +/* $Id: ip27-berr.c,v 1.1 2000/01/20 22:50:29 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-init.c linux/arch/mips64/sgi-ip27/ip27-init.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-init.c Thu Mar 2 14:36:22 2000 +++ linux/arch/mips64/sgi-ip27/ip27-init.c Mon May 15 12:10:26 2000 @@ -1,5 +1,11 @@ +#include #include +#include +#include #include /* for numnodes */ +#include +#include +#include #include #include #include @@ -8,16 +14,33 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include -typedef unsigned long cpumask_t; /* into asm/sn/types.h */ -typedef unsigned long cpuid_t; +#define CPU_NONE (cpuid_t)-1 #define CPUMASK_CLRALL(p) (p) = 0 #define CPUMASK_SETB(p, bit) (p) |= 1 << (bit) +#define CPUMASK_CLRB(p, bit) (p) &= ~(1ULL << (bit)) +#define CPUMASK_TSTB(p, bit) ((p) & (1ULL << (bit))) + +#define CNODEMASK_CLRALL(p) (p) = 0 +#define CNODEMASK_TSTB(p, bit) ((p) & (1ULL << (bit))) +#define CNODEMASK_SETB(p, bit) ((p) |= 1ULL << (bit)) cpumask_t boot_cpumask; +static volatile cpumask_t boot_barrier; hubreg_t region_mask = 0; static int fine_mode = 0; +int maxcpus; +static spinlock_t hub_mask_lock = SPIN_LOCK_UNLOCKED; +static cnodemask_t hub_init_mask; cnodeid_t nasid_to_compact_node[MAX_NASIDS]; nasid_t compact_to_nasid_node[MAX_COMPACT_NODES]; @@ -47,51 +70,6 @@ >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE); } -lboard_t * find_lboard_real(lboard_t *start, unsigned char brd_type) -{ - /* Search all boards stored on this node. */ - while (start) { - if (start->brd_type == brd_type) - return start; - start = KLCF_NEXT(start); - } - /* Didn't find it. */ - return (lboard_t *)NULL; -} - -klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type) -{ - int index, j; - - if (kli == (klinfo_t *)NULL) { - index = 0; - } else { - for (j = 0; j < KLCF_NUM_COMPS(brd); j++) - if (kli == KLCF_COMP(brd, j)) - break; - index = j; - if (index == KLCF_NUM_COMPS(brd)) { - printk("find_component: Bad pointer: 0x%p\n", kli); - return (klinfo_t *)NULL; - } - index++; /* next component */ - } - - for (; index < KLCF_NUM_COMPS(brd); index++) { - kli = KLCF_COMP(brd, index); - if (KLCF_COMP_TYPE(kli) == struct_type) - return kli; - } - - /* Didn't find it. */ - return (klinfo_t *)NULL; -} - -klinfo_t *find_first_component(lboard_t *brd, unsigned char struct_type) -{ - return find_component(brd, (klinfo_t *)NULL, struct_type); -} - nasid_t get_actual_nasid(lboard_t *brd) { klhub_t *hub; @@ -117,7 +95,7 @@ int cpus_found = 0; cpuid_t cpuid; - brd = find_lboard_real((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); do { acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU); @@ -138,7 +116,7 @@ } brd = KLCF_NEXT(brd); if (brd) - brd = find_lboard_real(brd,KLTYPE_IP27); + brd = find_lboard(brd,KLTYPE_IP27); else break; } while (brd); @@ -182,9 +160,38 @@ return(highest + 1); } +void alloc_cpupda(int i) +{ + cnodeid_t node; + nasid_t nasid; + + node = get_cpu_cnode(i); + nasid = COMPACT_TO_NASID_NODEID(node); + + cputonasid(i) = nasid; + cputocnode(i) = node; + cputoslice(i) = get_cpu_slice(i); +} + +int cpu_enabled(cpuid_t cpu) +{ + if (cpu == CPU_NONE) + return 0; + return (CPUMASK_TSTB(boot_cpumask, cpu) != 0); +} + +void initpdas(void) +{ + cpuid_t i; + + for (i = 0; i < maxcpus; i++) + if (cpu_enabled(i)) + alloc_cpupda(i); +} + void mlreset (void) { - int i, maxcpus; + int i; fine_mode = is_fine_dirmode(); @@ -194,8 +201,11 @@ */ CPUMASK_CLRALL(boot_cpumask); maxcpus = cpu_node_probe(&boot_cpumask, &numnodes); + printk("Discovered %d cpus on %d nodes\n", maxcpus, numnodes); + initpdas(); gen_region_mask(®ion_mask, numnodes); + CNODEMASK_CLRALL(hub_init_mask); /* * Set all nodes' calias sizes to 8k @@ -225,3 +235,257 @@ } } + +void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend, int base_level, + char *name) +{ + volatile hubreg_t bits; + int i; + + /* Check pending interrupts */ + if ((bits = HUB_L(pend)) != 0) + for (i = 0; i < N_INTPEND_BITS; i++) + if (bits & (1 << i)) + LOCAL_HUB_CLR_INTR(base_level + i); +} + +void intr_clear_all(nasid_t nasid) +{ + REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0); + REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0); + REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0); + REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0); + intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND0), + INT_PEND0_BASELVL, "INT_PEND0"); + intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1), + INT_PEND1_BASELVL, "INT_PEND1"); +} + +void sn_mp_setup(void) +{ + cnodeid_t cnode; +#if 0 + cpuid_t cpu; +#endif + + for (cnode = 0; cnode < numnodes; cnode++) { +#if 0 + init_platform_nodepda(); +#endif + intr_clear_all(COMPACT_TO_NASID_NODEID(cnode)); + } +#if 0 + for (cpu = 0; cpu < maxcpus; cpu++) { + init_platform_pda(); + } +#endif +} + +void per_hub_init(cnodeid_t cnode) +{ + cnodemask_t done; + + spin_lock(&hub_mask_lock); + /* Test our bit. */ + if (!(done = CNODEMASK_TSTB(hub_init_mask, cnode))) { + /* Turn our bit on in the mask. */ + CNODEMASK_SETB(hub_init_mask, cnode); + } + spin_unlock(&hub_mask_lock); + + /* + * Do the actual initialization if it hasn't been done yet. + * We don't need to hold a lock for this work. + */ + if (!done) { + hub_rtc_init(cnode); + } +} + +/* + * This is similar to hard_smp_processor_id(). + */ +cpuid_t getcpuid(void) +{ + klcpu_t *klcpu; + + klcpu = nasid_slice_to_cpuinfo(get_nasid(),LOCAL_HUB_L(PI_CPU_NUM)); + return klcpu->cpu_info.virtid; +} + +void per_cpu_init(void) +{ + extern void install_cpu_nmi_handler(int slice); + extern void load_mmu(void); + static int is_slave = 0; + cpuid_t cpu = getcpuid(); + cnodeid_t cnode = get_compact_nodeid(); + + current_cpu_data.asid_cache = ASID_FIRST_VERSION; +#if 0 + intr_init(); +#endif + set_cp0_status(ST0_IM, 0); + per_hub_init(cnode); + cpu_time_init(); + if (smp_processor_id()) /* master can't do this early, no kmalloc */ + install_cpuintr(cpu); + /* Install our NMI handler if symmon hasn't installed one. */ + install_cpu_nmi_handler(cputoslice(smp_processor_id())); +#if 0 + install_tlbintr(cpu); +#endif + set_cp0_status(SRB_DEV0 | SRB_DEV1, SRB_DEV0 | SRB_DEV1); + if (is_slave) { + set_cp0_status(ST0_BEV, 0); + if (mips4_available) + set_cp0_status(ST0_XX, ST0_XX); + set_cp0_status(ST0_KX|ST0_SX|ST0_UX, ST0_KX|ST0_SX|ST0_UX); + sti(); + load_mmu(); + } + if (is_slave == 0) + is_slave = 1; +} + +cnodeid_t get_compact_nodeid(void) +{ + nasid_t nasid; + + nasid = get_nasid(); + /* + * Map the physical node id to a virtual node id (virtual node ids + * are contiguous). + */ + return NASID_TO_COMPACT_NODEID(nasid); +} + +#ifdef CONFIG_SMP + +void __init smp_callin(void) +{ +#if 0 + calibrate_delay(); + smp_store_cpu_info(cpuid); +#endif +} + +int __init start_secondary(void) +{ + extern int cpu_idle(void); + extern atomic_t smp_commenced; + + smp_callin(); + while (!atomic_read(&smp_commenced)); + return cpu_idle(); +} + +static atomic_t numstarted = ATOMIC_INIT(0); +void cboot(void) +{ + atomic_inc(&numstarted); + CPUMASK_CLRB(boot_barrier, getcpuid()); /* needs atomicity */ + per_cpu_init(); +#if 0 + ecc_init(); + bte_lateinit(); + init_mfhi_war(); +#endif + _flush_tlb_all(); + flush_cache_all(); + start_secondary(); +} + +void allowboot(void) +{ + int num_cpus = 0; + cpuid_t cpu; + cnodeid_t cnode; + extern void bootstrap(void); + + sn_mp_setup(); + /* Master has already done per_cpu_init() */ + install_cpuintr(getcpuid()); +#if 0 + bte_lateinit(); + ecc_init(); +#endif + + boot_barrier = boot_cpumask; + /* Launch slaves. */ + for (cpu = 0; cpu < maxcpus; cpu++) { + if (cpu == smp_processor_id()) { + num_cpus++; + /* We're already started, clear our bit */ + CPUMASK_CLRB(boot_barrier, cpu); + continue; + } + + /* Skip holes in CPU space */ + if (CPUMASK_TSTB(boot_cpumask, cpu)) { + struct task_struct *p; + + /* + * The following code is purely to make sure + * Linux can schedule processes on this slave. + */ + kernel_thread(0, NULL, CLONE_PID); + p = init_task.prev_task; + sprintf(p->comm, "%s%d", "Idle", num_cpus); + init_tasks[num_cpus] = p; + p->processor = num_cpus; + p->has_cpu = 1; /* we schedule the first task manually */ + del_from_runqueue(p); + unhash_process(p); + /* Attach to the address space of init_task. */ + atomic_inc(&init_mm.mm_count); + p->active_mm = &init_mm; + + /* + * Launch a slave into bootstrap(). + * It doesn't take an argument, and we + * set sp to the kernel stack of the newly + * created idle process, gp to the proc struct + * (so that current-> works). + */ + LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu), + (launch_proc_t)bootstrap, 0, + (void *)((unsigned long)p+KERNEL_STACK_SIZE - 32), + (void *)p); + + /* + * Now optimistically set the mapping arrays. We + * need to wait here, verify the cpu booted up, then + * fire up the next cpu. + */ + __cpu_number_map[cpu] = num_cpus; + __cpu_logical_map[num_cpus] = cpu; + num_cpus++; + /* smp_num_cpus++; Do after smp_send_reschedule works */ + } + } + + /* while(atomic_read(&numstarted) != (maxcpus - num_cpus)) */ + if (maxcpus > 1) while(atomic_read(&numstarted) == 0); + printk("Holding %d cpus slave\n", atomic_read(&numstarted)); + +#ifdef LATER + Wait logic goes here. +#endif + for (cnode = 0; cnode < numnodes; cnode++) { +#if 0 + if (cnodetocpu(cnode) == -1) { + printk("Initializing headless hub,cnode %d", cnode); + per_hub_init(cnode); + } +#endif + } +#if 0 + cpu_io_setup(); + init_mfhi_war(); +#endif +} + +#else /* CONFIG_SMP */ +void cboot(void) {} +#endif /* CONFIG_SMP */ diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-irq-glue.S linux/arch/mips64/sgi-ip27/ip27-irq-glue.S --- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-irq-glue.S Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip27/ip27-irq-glue.S Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ip27-irq-glue.S,v 1.1 2000/01/17 23:32:47 ralf Exp $ +/* $Id$ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-irq.c linux/arch/mips64/sgi-ip27/ip27-irq.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-irq.c Thu Mar 2 14:36:22 2000 +++ linux/arch/mips64/sgi-ip27/ip27-irq.c Mon May 15 12:10:26 2000 @@ -1,14 +1,14 @@ -/* $Id: ip27-irq.c,v 1.6 2000/02/10 05:58:56 dagum Exp $ +/* $Id: ip27-irq.c,v 1.9 2000/03/14 01:39:27 ralf Exp $ * * ip27-irq.c: Highlevel interrupt handling for IP27 architecture. * * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999 Silicon Graphics, Inc. */ +#include #include #include -#include #include #include #include @@ -17,8 +17,9 @@ #include #include #include -#include #include +#include +#include #include #include @@ -33,14 +34,58 @@ #include #include #include +#include +#include + +#undef DEBUG_IRQ +#ifdef DEBUG_IRQ +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + + +/* + * Linux has a controller-independent x86 interrupt architecture. + * every controller has a 'controller-template', that is used + * by the main code to do the right thing. Each driver-visible + * interrupt source is transparently wired to the apropriate + * controller. Thus drivers need not be aware of the + * interrupt-controller. + * + * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, + * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. + * (IO-APICs assumed to be messaging to Pentium local-APICs) + * + * the code is designed to be easily extended with new/different + * interrupt controllers, without having to do assembly magic. + */ + +irq_cpustat_t irq_stat [NR_CPUS]; extern asmlinkage void ip27_irq(void); int (*irq_cannonicalize)(int irq); +int intr_connect_level(cpuid_t cpu, int bit); +int intr_disconnect_level(cpuid_t cpu, int bit); unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; unsigned long spurious_count = 0; +/* + * we need to map irq's up to at least bit 7 of the INT_MASK0_A register + * since bits 0-6 are pre-allocated for other purposes. + */ +#define IRQ_TO_SWLEVEL(i) i + 7 +#define SWLEVEL_TO_IRQ(s) s - 7 +/* + * use these macros to get the encoded nasid, widget id, and real irq + * from the irq value + */ +#define NASID_FROM_IRQ(i) ((i >> 16)&(0xff)) +#define WID_FROM_IRQ(i) ((i >> 8)&(0xff)) +#define IRQ_FROM_IRQ(i) ((i)&(0xff)) + void disable_irq(unsigned int irq_nr) { panic("disable_irq() called ..."); @@ -87,7 +132,7 @@ int do_random, cpu; cpu = smp_processor_id(); - irq_enter(cpu); + irq_enter(cpu, irq); kstat.irqs[cpu][irq]++; action = *(irq + irq_action); @@ -105,7 +150,7 @@ add_interrupt_randomness(irq); __cli(); } - irq_exit(cpu); + irq_exit(cpu, irq); /* unmasking and bottom half handling is done magically for us. */ } @@ -130,20 +175,26 @@ /* For now ... */ void ip27_do_irq(struct pt_regs *regs) { - int irq; + int irq, swlevel; hubreg_t pend0, mask0; + int pi_int_mask0 = ((cputoslice(smp_processor_id()) == 0) ? + PI_INT_MASK0_A : PI_INT_MASK0_B); /* copied from Irix intpend0() */ while (((pend0 = LOCAL_HUB_L(PI_INT_PEND0)) & - (mask0 = LOCAL_HUB_L(PI_INT_MASK0_A))) != 0) { + (mask0 = LOCAL_HUB_L(pi_int_mask0))) != 0) { + pend0 &= mask0; do { - irq = ms1bit(pend0); - LOCAL_HUB_S(PI_INT_MASK0_A, mask0 & ~(1 << irq)); - LOCAL_HUB_S(PI_INT_PEND_MOD, irq); - LOCAL_HUB_L(PI_INT_MASK0_A); /* Flush */ + swlevel = ms1bit(pend0); + LOCAL_HUB_S(pi_int_mask0, mask0 & ~(1 << swlevel)); + LOCAL_HUB_CLR_INTR(swlevel); + /* "map" swlevel to irq */ + irq = SWLEVEL_TO_IRQ(swlevel); do_IRQ(irq, regs); - LOCAL_HUB_S(PI_INT_MASK0_A, mask0); - pend0 ^= 1ULL << irq; + /* reset INT_MASK0 register */ + LOCAL_HUB_S(pi_int_mask0, mask0); + /* clear bit in pend0 */ + pend0 ^= 1ULL << swlevel; } while (pend0); } } @@ -152,96 +203,141 @@ /* Startup one of the (PCI ...) IRQs routes over a bridge. */ static unsigned int bridge_startup(unsigned int irq) { - bridge_t *bridge = (bridge_t *) 0x9200000008000000; - bridgereg_t br; - int pin; + bridge_t *bridge; + int pin, swlevel; + int real_irq = IRQ_FROM_IRQ(irq); + + DBG("bridge_startup(): irq= 0x%x real_irq= %d\n", irq, real_irq); + bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_IRQ(irq), WID_FROM_IRQ(irq)); + + /* FIIIIIXME ... Temporary kludge. This knows how interrupts are + setup in _my_ Origin. */ + + if (irq != real_irq) /* pci device interrupt */ + switch (real_irq) { + case IRQ_FROM_IRQ(IOC3_ETH_INT): pin = 2; break; + default: pin = real_irq; break; + } + else + switch (real_irq) { + case CPU_RESCHED_A_IRQ: + case CPU_RESCHED_B_IRQ: + case CPU_CALL_A_IRQ: + case CPU_CALL_B_IRQ: + return 0; + default: panic("bridge_startup: whoops? %d\n", irq); + } + + /* + * "map" irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken + */ + swlevel = IRQ_TO_SWLEVEL(real_irq); + intr_connect_level(smp_processor_id(), swlevel); + + bridge->b_int_addr[pin].addr = 0x20000 | swlevel; + bridge->b_int_enable |= (1 << pin); + /* set more stuff in int_enable reg */ + bridge->b_int_enable |= 0x7ffffe00; - /* FIIIIIXME ... Temporary kludge. This knows how interrupts are - setup in _my_ Origin. */ - switch (irq) { - case IOC3_SERIAL_INT: pin = 3; break; - case IOC3_ETH_INT: pin = 2; break; - case SCSI1_INT: pin = 1; break; - case SCSI0_INT: pin = 0; break; - default: panic("bridge_startup: whoops?"); - } - - br = LOCAL_HUB_L(PI_INT_MASK0_A); - LOCAL_HUB_S(PI_INT_MASK0_A, br | (1 << irq)); - LOCAL_HUB_L(PI_INT_MASK0_A); /* Flush */ - - bridge->b_int_addr[pin].addr = 0x20000 | irq; - bridge->b_int_enable |= (1 << pin); - if (irq < 2) { - bridgereg_t device; + if (real_irq < 2 || real_irq==4 || real_irq==5) { + bridgereg_t device; #if 0 - /* - * Allocate enough RRBs on the bridge for the DMAs. - * Right now allocating 2 RRBs on the normal channel - * and 2 on the virtual channel for slot 0 on the bus. - * And same for slot 1, to get ioc3 eth working. - */ - Not touching b_even_resp /* boot doesn't go far */ - bridge->b_even_resp = 0xdd99cc88; /* boot doesn't go far */ - bridge->b_even_resp = 0xcccc8888; /* breaks eth0 */ - bridge->b_even_resp = 0xcc88; /* breaks eth0 */ + /* + * Allocate enough RRBs on the bridge for the DMAs. + * Right now allocating 2 RRBs on the normal channel + * and 2 on the virtual channel for slot 0 on the bus. + * And same for slot 1, to get ioc3 eth working. + */ + Not touching b_even_resp /* boot doesn't go far */ + bridge->b_even_resp = 0xdd99cc88; /* boot doesn't go far */ + bridge->b_even_resp = 0xcccc8888; /* breaks eth0 */ + bridge->b_even_resp = 0xcc88; /* breaks eth0 */ #endif - /* Turn on bridge swapping */ - device = bridge->b_device[irq].reg; - device |= BRIDGE_DEV_SWAP_DIR; - bridge->b_device[irq].reg = device; - } - bridge->b_widget.w_tflush; /* Flush */ + /* Turn on bridge swapping */ + device = bridge->b_device[real_irq].reg; + device |= BRIDGE_DEV_SWAP_DIR; + bridge->b_device[real_irq].reg = device; + /* + * Associate interrupt pin with device + * XXX This only works if b_int_device is initialized to 0! + */ + device = bridge->b_int_device; + device |= (pin << (real_irq*3)); + bridge->b_int_device = device; + } + bridge->b_widget.w_tflush; /* Flush */ - return 0; /* Never anything pending. */ + return 0; /* Never anything pending. */ } -/* Startup one of the (PCI ...) IRQs routes over a bridge. */ +/* Shutdown one of the (PCI ...) IRQs routes over a bridge. */ static unsigned int bridge_shutdown(unsigned int irq) { - bridge_t *bridge = (bridge_t *) 0x9200000008000000; - bridgereg_t br; - int pin; + bridge_t *bridge; + int pin, swlevel; + int real_irq = IRQ_FROM_IRQ(irq); + struct irqaction **p; + + bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_IRQ(irq), WID_FROM_IRQ(irq)); + DBG("bridge_shutdown: irq 0x%x\n", irq); + /* FIIIIIXME ... Temporary kludge. This knows how interrupts are + setup in _my_ Origin. */ + + if (irq != real_irq) /* pci device interrupt */ + switch (real_irq) { + case IRQ_FROM_IRQ(IOC3_ETH_INT): pin = 2; break; + default: pin = real_irq; break; + } + else + switch (real_irq) { + case CPU_RESCHED_A_IRQ: + case CPU_RESCHED_B_IRQ: + case CPU_CALL_A_IRQ: + case CPU_CALL_B_IRQ: + return 0; + default: panic("bridge_startup: whoops?"); + } + + /* + * map irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken + */ + swlevel = IRQ_TO_SWLEVEL(real_irq); + intr_disconnect_level(smp_processor_id(), swlevel); - /* FIIIIIXME ... Temporary kludge. This knows how interrupts are - setup in _my_ Origin. */ - switch (irq) { - case IOC3_SERIAL_INT: pin = 3; break; - case IOC3_ETH_INT: pin = 2; break; - case SCSI1_INT: pin = 1; break; - case SCSI0_INT: pin = 0; break; - default: panic("bridge_startup: whoops?"); - } - - br = LOCAL_HUB_L(PI_INT_MASK0_A); - LOCAL_HUB_S(PI_INT_MASK0_A, br & ~(1 << irq)); - LOCAL_HUB_L(PI_INT_MASK0_A); /* Flush */ + bridge->b_int_enable &= ~(1 << pin); + bridge->b_widget.w_tflush; /* Flush */ - bridge->b_int_enable &= ~(1 << pin); - bridge->b_widget.w_tflush; /* Flush */ - - return 0; /* Never anything pending. */ + return 0; /* Never anything pending. */ } static void bridge_init(void) { - bridge_t *bridge = (bridge_t *) 0x9200000008000000; - - /* Hmm... IRIX sets additional bits in the address which are - documented as reserved in the bridge docs ... */ - bridge->b_int_mode = 0x0; /* Don't clear ints */ + bridge_t *bridge; + nasid_t nasid; + char wid; + int bus; + + nasid = get_nasid(); + + for (bus=0; busb_int_mode = 0x0; /* Don't clear ints */ #if 0 - bridge->b_wid_int_upper = 0x000a8000; /* Ints to node 0 */ - bridge->b_wid_int_lower = 0x01000090; - bridge->b_dir_map = 0xa00000; /* DMA */ + bridge->b_wid_int_upper = 0x000a8000; /* Ints to node 0 */ + bridge->b_wid_int_lower = 0x01000090; + bridge->b_dir_map = 0xa00000; /* DMA */ #endif /* shouldn't lower= 0x01800090 ??? */ - bridge->b_wid_int_upper = 0x00098000; /* Ints to node 0 */ - bridge->b_wid_int_lower = 0x01800090; - bridge->b_dir_map = 0x900000; /* DMA */ - - bridge->b_int_enable = 0; - bridge->b_widget.w_tflush; /* Flush */ - set_cp0_status(SRB_DEV0 | SRB_DEV1, SRB_DEV0 | SRB_DEV1); + bridge->b_wid_int_upper = 0x000a8000; /* Ints to widget A */ + bridge->b_wid_int_lower = 0x01800090; + bridge->b_dir_map = 0xa00000; /* DMA */ + + bridge->b_int_enable = 0; + bridge->b_widget.w_tflush; /* Flush */ + } } void irq_debug(void) @@ -254,17 +350,18 @@ printk("PI_INT_MASK0_A = 0x%x\n", LOCAL_HUB_L(PI_INT_MASK0_A)); } -int setup_irq(int irq, struct irqaction *new) +int setup_irq(unsigned int irq, struct irqaction *new) { int shared = 0; struct irqaction *old, **p; unsigned long flags; + DBG("setup_irq: 0x%x\n", irq); if (new->flags & SA_SAMPLE_RANDOM) rand_initialize_irq(irq); save_and_cli(flags); - p = irq_action + irq; + p = irq_action + IRQ_FROM_IRQ(irq); if ((old = *p) != NULL) { /* Can't share interrupts unless both agree to */ if (!(old->flags & new->flags & SA_SHIRQ)) { @@ -297,7 +394,8 @@ int retval; struct irqaction *action; - if (irq > 9) + DBG("request_irq(): irq= 0x%x\n", irq); + if (IRQ_FROM_IRQ(irq) > 9) return -EINVAL; if (!handler) return -EINVAL; @@ -313,7 +411,9 @@ action->next = NULL; action->dev_id = dev_id; + DBG("request_irq(): %s devid= 0x%x\n", devname, dev_id); retval = setup_irq(irq, action); + DBG("request_irq(): retval= %d\n", retval); if (retval) kfree(action); return retval; @@ -324,11 +424,11 @@ struct irqaction * action, **p; unsigned long flags; - if (irq > 9) { + if (IRQ_FROM_IRQ(irq) > 9) { printk("Trying to free IRQ%d\n", irq); return; } - for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { + for (p = IRQ_FROM_IRQ(irq) + irq_action; (action = *p) != NULL; p = &action->next) { if (action->dev_id != dev_id) continue; @@ -347,6 +447,7 @@ /* Useless ISA nonsense. */ unsigned long probe_irq_on (void) { + panic("probe_irq_on called!\n"); return 0; } @@ -366,4 +467,313 @@ bridge_init(); set_except_vector(0, ip27_irq); +} + + +#ifdef CONFIG_SMP + +/* + * This following are the global intr on off routines, copied almost + * entirely from i386 code. + */ + +int global_irq_holder = NO_PROC_ID; +spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED; + +extern void show_stack(unsigned long* esp); + +static void show(char * str) +{ + int i; + int cpu = smp_processor_id(); + + printk("\n%s, CPU %d:\n", str, cpu); + printk("irq: %d [",irqs_running()); + for(i=0;i < smp_num_cpus;i++) + printk(" %d",local_irq_count(i)); + printk(" ]\nbh: %d [",spin_is_locked(&global_bh_lock) ? 1 : 0); + for(i=0;i < smp_num_cpus;i++) + printk(" %d",local_bh_count(i)); + + printk(" ]\nStack dumps:"); + for(i = 0; i < smp_num_cpus; i++) { + unsigned long esp; + if (i == cpu) + continue; + printk("\nCPU %d:",i); + printk("Code not developed yet\n"); + /* show_stack(0); */ + } + printk("\nCPU %d:",cpu); + printk("Code not developed yet\n"); + /* show_stack(NULL); */ + printk("\n"); +} + +#define MAXCOUNT 100000000 +#define SYNC_OTHER_CORES(x) udelay(x+1) + +static inline void wait_on_irq(int cpu) +{ + int count = MAXCOUNT; + + for (;;) { + + /* + * Wait until all interrupts are gone. Wait + * for bottom half handlers unless we're + * already executing in one.. + */ + if (!irqs_running()) + if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock)) + break; + + /* Duh, we have to loop. Release the lock to avoid deadlocks */ + spin_unlock(&global_irq_lock); + + for (;;) { + if (!--count) { + show("wait_on_irq"); + count = ~0; + } + __sti(); + SYNC_OTHER_CORES(cpu); + __cli(); + if (irqs_running()) + continue; + if (spin_is_locked(&global_irq_lock)) + continue; + if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock)) + continue; + if (spin_trylock(&global_irq_lock)) + break; + } + } +} + +void synchronize_irq(void) +{ + if (irqs_running()) { + /* Stupid approach */ + cli(); + sti(); + } +} + +static inline void get_irqlock(int cpu) +{ + if (!spin_trylock(&global_irq_lock)) { + /* do we already hold the lock? */ + if ((unsigned char) cpu == global_irq_holder) + return; + /* Uhhuh.. Somebody else got it. Wait.. */ + spin_lock(&global_irq_lock); + } + /* + * We also to make sure that nobody else is running + * in an interrupt context. + */ + wait_on_irq(cpu); + + /* + * Ok, finally.. + */ + global_irq_holder = cpu; +} + +void __global_cli(void) +{ + unsigned int flags; + + __save_flags(flags); + if (flags & ST0_IE) { + int cpu = smp_processor_id(); + __cli(); + if (!local_irq_count(cpu)) + get_irqlock(cpu); + } +} + +void __global_sti(void) +{ + int cpu = smp_processor_id(); + + if (!local_irq_count(cpu)) + release_irqlock(cpu); + __sti(); +} + +/* + * SMP flags value to restore to: + * 0 - global cli + * 1 - global sti + * 2 - local cli + * 3 - local sti + */ +unsigned long __global_save_flags(void) +{ + int retval; + int local_enabled; + unsigned long flags; + int cpu = smp_processor_id(); + + __save_flags(flags); + local_enabled = (flags & ST0_IE); + /* default to local */ + retval = 2 + local_enabled; + + /* check for global flags if we're not in an interrupt */ + if (!local_irq_count(cpu)) { + if (local_enabled) + retval = 1; + if (global_irq_holder == cpu) + retval = 0; + } + return retval; +} + +void __global_restore_flags(unsigned long flags) +{ + switch (flags) { + case 0: + __global_cli(); + break; + case 1: + __global_sti(); + break; + case 2: + __cli(); + break; + case 3: + __sti(); + break; + default: + printk("global_restore_flags: %08lx\n", flags); + } +} + +#endif /* CONFIG_SMP */ + +/* + * Get values that vary depending on which CPU and bit we're operating on. + */ +static hub_intmasks_t *intr_get_ptrs(cpuid_t cpu, int bit, int *new_bit, + hubreg_t **intpend_masks, int *ip) +{ + hub_intmasks_t *hub_intmasks; + + hub_intmasks = &cpu_data[cpu].p_intmasks; + if (bit < N_INTPEND_BITS) { + *intpend_masks = hub_intmasks->intpend0_masks; + *ip = 0; + *new_bit = bit; + } else { + *intpend_masks = hub_intmasks->intpend1_masks; + *ip = 1; + *new_bit = bit - N_INTPEND_BITS; + } + return hub_intmasks; +} + +int intr_connect_level(cpuid_t cpu, int bit) +{ + int ip; + int slice = cputoslice(cpu); + volatile hubreg_t *mask_reg; + hubreg_t *intpend_masks; + nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu)); + + (void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &ip); + + /* Make sure it's not already pending when we connect it. */ + REMOTE_HUB_CLR_INTR(nasid, bit + ip * N_INTPEND_BITS); + + intpend_masks[0] |= (1ULL << (u64)bit); + + if (ip == 0) { + mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A + + PI_INT_MASK_OFFSET * slice); + } else { + mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A + + PI_INT_MASK_OFFSET * slice); + } + HUB_S(mask_reg, intpend_masks[0]); + return(0); +} + +int intr_disconnect_level(cpuid_t cpu, int bit) +{ + int ip; + int slice = cputoslice(cpu); + volatile hubreg_t *mask_reg; + hubreg_t *intpend_masks; + nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu)); + + (void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &ip); + intpend_masks[0] &= ~(1ULL << (u64)bit); + if (ip == 0) { + mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A + + PI_INT_MASK_OFFSET * slice); + } else { + mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A + + PI_INT_MASK_OFFSET * slice); + } + HUB_S(mask_reg, intpend_masks[0]); + return(0); +} + + +void handle_resched_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + /* Nothing, the return from intr will work for us */ +} + +void install_cpuintr(cpuid_t cpu) +{ + int irq; + extern void smp_call_function_interrupt(void); + static int done = 0; + + /* + * This is a hack till we have a pernode irqlist. Currently, + * just have the master cpu set up the handlers for the per + * cpu irqs. + */ + +#ifdef CONFIG_SMP +#if (CPUS_PER_NODE == 2) + irq = CPU_RESCHED_A_IRQ + cputoslice(cpu); + intr_connect_level(cpu, IRQ_TO_SWLEVEL(irq)); + if (done == 0) + if (request_irq(irq, handle_resched_intr, 0, "resched", 0)) + panic("intercpu intr unconnectible\n"); + irq = CPU_CALL_A_IRQ + cputoslice(cpu); + intr_connect_level(cpu, IRQ_TO_SWLEVEL(irq)); + if (done == 0) + if (request_irq(irq, smp_call_function_interrupt, 0, + "callfunc", 0)) + panic("intercpu intr unconnectible\n"); + /* HACK STARTS */ + if (done) + return; + irq = CPU_RESCHED_A_IRQ + cputoslice(cpu) + 1; + if (request_irq(irq, handle_resched_intr, 0, "resched", 0)) + panic("intercpu intr unconnectible\n"); + irq = CPU_CALL_A_IRQ + cputoslice(cpu) + 1; + if (request_irq(irq, smp_call_function_interrupt, 0, + "callfunc", 0)) + panic("intercpu intr unconnectible\n"); + done = 1; + /* HACK ENDS */ +#else /* CPUS_PER_NODE */ + << Bomb! Must redefine this for more than 2 CPUS. >> +#endif /* CPUS_PER_NODE */ +#endif /* CONFIG_SMP */ +} + +void install_tlbintr(cpuid_t cpu) +{ + int intr_bit = N_INTPEND_BITS + TLB_INTR_A + cputoslice(cpu); + + intr_connect_level(cpu, intr_bit); } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-klconfig.c linux/arch/mips64/sgi-ip27/ip27-klconfig.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-klconfig.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip27/ip27-klconfig.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ip27-klconfig.c,v 1.1 2000/01/17 23:32:47 ralf Exp $ +/* $Id$ * * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. @@ -13,21 +13,111 @@ #include #include +#include +#include -lboard_t *find_lboard(unsigned int type) +klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type) { - lboard_t *b; + int index, j; - for ( -b = KL_CONFIG_INFO(get_nasid()); -b; -b = KLCF_NEXT(b)) { - if (KLCF_REMOTE(b)) - continue; /* Skip remote boards. */ + if (kli == (klinfo_t *)NULL) { + index = 0; + } else { + for (j = 0; j < KLCF_NUM_COMPS(brd); j++) + if (kli == KLCF_COMP(brd, j)) + break; + index = j; + if (index == KLCF_NUM_COMPS(brd)) { + printk("find_component: Bad pointer: 0x%p\n", kli); + return (klinfo_t *)NULL; + } + index++; /* next component */ + } + + for (; index < KLCF_NUM_COMPS(brd); index++) { + kli = KLCF_COMP(brd, index); + if (KLCF_COMP_TYPE(kli) == struct_type) + return kli; + } + + /* Didn't find it. */ + return (klinfo_t *)NULL; +} + +klinfo_t *find_first_component(lboard_t *brd, unsigned char struct_type) +{ + return find_component(brd, (klinfo_t *)NULL, struct_type); +} + +lboard_t * find_lboard(lboard_t *start, unsigned char brd_type) +{ + /* Search all boards stored on this node. */ + while (start) { + if (start->brd_type == brd_type) + return start; + start = KLCF_NEXT(start); + } + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +cnodeid_t get_cpu_cnode(int cpu) +{ + return CPUID_TO_COMPACT_NODEID(cpu); +} + +klcpu_t * nasid_slice_to_cpuinfo(nasid_t nasid, int slice) +{ + lboard_t *brd; + klcpu_t *acpu; + + if (!(brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27))) + return (klcpu_t *)NULL; + + if (!(acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU))) + return (klcpu_t *)NULL; + + do { + if ((acpu->cpu_info.physid) == slice) + return acpu; + } while ((acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu, + KLSTRUCT_CPU))); + return (klcpu_t *)NULL; +} + +klcpu_t * sn_get_cpuinfo(cpuid_t cpu) +{ + nasid_t nasid; + int slice; + klcpu_t *acpu; + gda_t *gdap = GDA; + cnodeid_t cnode; - if (b->brd_type == type) - return (lboard_t *) b; + if (!(cpu < MAXCPUS)) { + printk("sn_get_cpuinfo: illegal cpuid 0x%lx\n", cpu); + return NULL; } + cnode = get_cpu_cnode(cpu); + if (cnode == INVALID_CNODEID) + return NULL; + + if ((nasid = gdap->g_nasidtable[cnode]) == INVALID_NASID) + return NULL; + + for (slice = 0; slice < CPUS_PER_NODE; slice++) { + acpu = nasid_slice_to_cpuinfo(nasid, slice); + if (acpu && acpu->cpu_info.virtid == cpu) + return acpu; + } return NULL; +} + +int get_cpu_slice(cpuid_t cpu) +{ + klcpu_t *acpu; + + if ((acpu = sn_get_cpuinfo(cpu)) == NULL) + return -1; + return acpu->cpu_info.physid; } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-memory.c linux/arch/mips64/sgi-ip27/ip27-memory.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-memory.c Tue Apr 11 15:09:13 2000 +++ linux/arch/mips64/sgi-ip27/ip27-memory.c Mon May 15 16:41:29 2000 @@ -1,4 +1,4 @@ -/* $Id: ip27-memory.c,v 1.9 2000/02/10 09:07:31 kanoj Exp $ +/* $Id: ip27-memory.c,v 1.2 2000/01/27 01:05:24 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -46,7 +46,7 @@ int numa_debug(void) { printk("NUMA debug\n"); - *(int *)0 = 0; + BUG(); return(0); } @@ -57,17 +57,12 @@ */ pfn_t node_getfirstfree(cnodeid_t cnode) { -#ifdef LATER nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); if (cnode == 0) - return KDM_TO_PHYS((unsigned long)(&_end)); - return KDM_TO_PHYS(SYMMON_STK_ADDR(nasid, 0)); -#endif - if (cnode == 0) return (KDM_TO_PHYS(PAGE_ALIGN((unsigned long)(&_end)) - (CKSEG0 - K0BASE)) >> PAGE_SHIFT); - return slot_getbasepfn(cnode, 0); + return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> PAGE_SHIFT); } /* @@ -124,7 +119,7 @@ nasid = COMPACT_TO_NASID_NODEID(node); /* Find the node board */ - brd = find_lboard_real((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); if (!brd) return 0; @@ -269,28 +264,24 @@ void __init paging_init(void) { cnodeid_t node; - unsigned int zones_size[MAX_NR_ZONES] = {0, 0, 0}; + unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); - pgd_init((unsigned long)swapper_pg_dir + PAGE_SIZE / 2); pmd_init((unsigned long)invalid_pmd_table); + memset((void *)invalid_pte_table, 0, sizeof(pte_t) * 2 * PTRS_PER_PTE); for (node = 0; node < numnodes; node++) { pfn_t start_pfn = slot_getbasepfn(node, 0); pfn_t end_pfn = node_getmaxclick(node); zones_size[ZONE_DMA] = end_pfn + 1 - start_pfn; - PLAT_NODE_DATA(node)->physstart = (start_pfn << PAGE_SHIFT); - PLAT_NODE_DATA(node)->size = (zones_size[ZONE_DMA] << PAGE_SHIFT); free_area_init_node(node, NODE_DATA(node), zones_size, start_pfn << PAGE_SHIFT, 0); - PLAT_NODE_DATA(node)->start_mapnr = - (NODE_DATA(node)->node_mem_map - mem_map); - if ((PLAT_NODE_DATA(node)->start_mapnr + - PLAT_NODE_DATA(node)->size) > pagenr) - pagenr = PLAT_NODE_DATA(node)->start_mapnr + - PLAT_NODE_DATA(node)->size; + if ((PLAT_NODE_DATA_STARTNR(node) + + PLAT_NODE_DATA_SIZE(node)) > pagenr) + pagenr = PLAT_NODE_DATA_STARTNR(node) + + PLAT_NODE_DATA_SIZE(node); } } @@ -314,6 +305,11 @@ for (nid = 0; nid < numnodes; nid++) { /* + * Hack till free_area_init_core() zeroes free_pages + */ + for (tmp = 0; tmp < MAX_NR_ZONES; tmp++) + PLAT_NODE_DATA(nid)->gendata.node_zones[tmp].free_pages=0; + /* * This will free up the bootmem, ie, slot 0 memory. */ totalram_pages += free_all_bootmem_node(nid); @@ -322,7 +318,7 @@ * We need to manually do the other slots. */ pg = NODE_DATA(nid)->node_mem_map + slot_getsize(nid, 0); - pgnr = PLAT_NODE_DATA(nid)->start_mapnr + slot_getsize(nid, 0); + pgnr = PLAT_NODE_DATA_STARTNR(nid) + slot_getsize(nid, 0); numslots = node_getlastslot(nid); for (slot = 1; slot <= numslots; slot++) { pslot = NODE_DATA(nid)->node_mem_map + @@ -357,9 +353,9 @@ reservedpages = ram = 0; for (nid = 0; nid < numnodes; nid++) { - for (tmp = PLAT_NODE_DATA(nid)->start_mapnr; tmp < - ((PLAT_NODE_DATA(nid)->start_mapnr) + - (PLAT_NODE_DATA(nid)->size >> PAGE_SHIFT)); tmp++) { + for (tmp = PLAT_NODE_DATA_STARTNR(nid); tmp < + (PLAT_NODE_DATA_STARTNR(nid) + + PLAT_NODE_DATA_SIZE(nid)); tmp++) { /* Ignore holes */ if (PageSkip(mem_map+tmp)) continue; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-nmi.c linux/arch/mips64/sgi-ip27/ip27-nmi.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-nmi.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/sgi-ip27/ip27-nmi.c Sat May 13 08:30:17 2000 @@ -0,0 +1,165 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#define NODE_NUM_CPUS(n) CNODE_NUM_CPUS(n) +#else +#define NODE_NUM_CPUS(n) CPUS_PER_NODE +#endif + +#define CNODEID_NONE (cnodeid_t)-1 +#define enter_panic_mode() spin_lock(&nmi_lock) + +typedef unsigned long machreg_t; + +spinlock_t nmi_lock = SPIN_LOCK_UNLOCKED; + +/* + * Lets see what else we need to do here. Set up sp, gp? + */ +void nmi_dump(void) +{ + void cont_nmi_dump(void); + + cont_nmi_dump(); +} + +void install_cpu_nmi_handler(int slice) +{ + nmi_t *nmi_addr; + + nmi_addr = (nmi_t *)NMI_ADDR(get_nasid(), slice); + if (nmi_addr->call_addr) + return; + nmi_addr->magic = NMI_MAGIC; + nmi_addr->call_addr = (void *)nmi_dump; + nmi_addr->call_addr_c = + (void *)(~((unsigned long)(nmi_addr->call_addr))); + nmi_addr->call_parm = 0; +} + +/* + * Copy the cpu registers which have been saved in the IP27prom format + * into the eframe format for the node under consideration. + */ + +void +nmi_cpu_eframe_save(nasid_t nasid, + int slice) +{ + int i, numberof_nmi_cpu_regs; + machreg_t *prom_format; + + /* Get the total number of registers being saved by the prom */ + numberof_nmi_cpu_regs = sizeof(struct reg_struct) / sizeof(machreg_t); + + /* Get the pointer to the current cpu's register set. */ + prom_format = + (machreg_t *)(TO_UNCAC(TO_NODE(nasid, IP27_NMI_KREGS_OFFSET)) + + slice * IP27_NMI_KREGS_CPU_SIZE); + + printk("NMI nasid %d: slice %d\n", nasid, slice); + for (i = 0; i < numberof_nmi_cpu_regs; i++) + printk("0x%lx ", prom_format[i]); + printk("\n\n"); +} + +/* + * Copy the cpu registers which have been saved in the IP27prom format + * into the eframe format for the node under consideration. + */ +void +nmi_node_eframe_save(cnodeid_t cnode) +{ + int cpu; + nasid_t nasid; + + /* Make sure that we have a valid node */ + if (cnode == CNODEID_NONE) + return; + + nasid = COMPACT_TO_NASID_NODEID(cnode); + if (nasid == INVALID_NASID) + return; + + /* Save the registers into eframe for each cpu */ + for(cpu = 0; cpu < NODE_NUM_CPUS(cnode); cpu++) + nmi_cpu_eframe_save(nasid, cpu); +} + +/* + * Save the nmi cpu registers for all cpus in the system. + */ +void +nmi_eframes_save(void) +{ + cnodeid_t cnode; + + for(cnode = 0 ; cnode < numnodes; cnode++) + nmi_node_eframe_save(cnode); +} + +void +cont_nmi_dump(void) +{ +#ifndef REAL_NMI_SIGNAL + static atomic_t nmied_cpus = ATOMIC_INIT(0); + + atomic_inc(&nmied_cpus); +#endif + /* + * Use enter_panic_mode to allow only 1 cpu to proceed + */ + enter_panic_mode(); + +#ifdef REAL_NMI_SIGNAL + /* + * Wait up to 15 seconds for the other cpus to respond to the NMI. + * If a cpu has not responded after 10 sec, send it 1 additional NMI. + * This is for 2 reasons: + * - sometimes a MMSC fail to NMI all cpus. + * - on 512p SN0 system, the MMSC will only send NMIs to + * half the cpus. Unfortunately, we dont know which cpus may be + * NMIed - it depends on how the site chooses to configure. + * + * Note: it has been measure that it takes the MMSC up to 2.3 secs to + * send NMIs to all cpus on a 256p system. + */ + for (i=0; i < 1500; i++) { + for (node=0; node < numnodes; node++) + if (NODEPDA(node)->dump_count == 0) + break; + if (node == numnodes) + break; + if (i == 1000) { + for (node=0; node < numnodes; node++) + if (NODEPDA(node)->dump_count == 0) { + cpu = CNODE_TO_CPU_BASE(node); + for (n=0; n < CNODE_NUM_CPUS(node); cpu++, n++) { + CPUMASK_SETB(nmied_cpus, cpu); + SEND_NMI((cputonasid(cpu)), (cputoslice(cpu))); + } + } + + } + udelay(10000); + } +#else + while (atomic_read(&nmied_cpus) != smp_num_cpus); +#endif + + /* + * Save the nmi cpu registers for all cpu in the eframe format. + */ + nmi_eframes_save(); + LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET); +} + diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-pci-dma.c linux/arch/mips64/sgi-ip27/ip27-pci-dma.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-pci-dma.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip27/ip27-pci-dma.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ip27-pci-dma.c,v 1.1 2000/02/18 00:24:31 ralf Exp $ +/* $Id: ip27-pci-dma.c,v 1.1 2000/02/16 21:22:00 ralf Exp $ * * Dynamic DMA mapping support. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-pci.c linux/arch/mips64/sgi-ip27/ip27-pci.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-pci.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip27/ip27-pci.c Sat May 13 08:30:17 2000 @@ -13,6 +13,8 @@ #include #include #include +#include +#include /* * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is @@ -22,14 +24,18 @@ */ #define CF0_READ_PCI_CFG(dev,where,value,bm,mask) \ do { \ - bridge_t *bridge = (bridge_t *) 0x9200000008000000; \ + bridge_t *bridge; \ int slot = PCI_SLOT(dev->devfn); \ int fn = PCI_FUNC(dev->devfn); \ volatile u32 *addr; \ u32 cf, __bit; \ + unsigned int bus_id = (unsigned) dev->bus->number; \ \ - if (dev->bus->number) \ - return PCIBIOS_DEVICE_NOT_FOUND; \ + bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], \ + bus_to_wid[bus_id]); \ + \ + /*if (dev->bus->number) */ \ + /* return PCIBIOS_DEVICE_NOT_FOUND; */ \ \ __bit = (((where) & (bm)) << 3); \ addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; \ @@ -59,14 +65,18 @@ #define CF0_WRITE_PCI_CFG(dev,where,value,bm,mask) \ do { \ - bridge_t *bridge = (bridge_t *) 0x9200000008000000; \ + bridge_t *bridge; \ int slot = PCI_SLOT(dev->devfn); \ int fn = PCI_FUNC(dev->devfn); \ volatile u32 *addr; \ u32 cf, __bit; \ + unsigned int bus_id = (unsigned) dev->bus->number; \ \ - if (dev->bus->number) \ - return PCIBIOS_DEVICE_NOT_FOUND; \ + bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], \ + bus_to_wid[bus_id]); \ + \ + /* if (dev->bus->number) */ \ + /* return PCIBIOS_DEVICE_NOT_FOUND; */ \ \ if (dev->vendor == PCI_VENDOR_ID_SGI \ && dev->device == PCI_DEVICE_ID_SGI_IOC3) \ @@ -114,11 +124,14 @@ { struct pci_ops *ops = &bridge_pci_ops; nasid_t nid = get_nasid(); + int i; ioport_resource.end = ~0UL; - printk("PCI: Probing PCI hardware on host bus 0, node %d.\n", nid); - pci_scan_bus(0, ops, NULL); + for (i=0; ibus->number] << 8); + rv |= (bus_to_nid[dev->bus->number] << 16); + return rv; } void __init @@ -171,33 +188,7 @@ void __init pcibios_fixup_bus(struct pci_bus *b) { - unsigned short command; - struct list_head *ln; - struct pci_dev *dev; - pci_fixup_irqs(pci_swizzle, pci_map_irq); - - /* - * Older qlogicisp driver expects to have the IO space enable - * bit set. Make that happen for qlogic in slots 0 and 1. Things - * stop working if we program the controllers as not having - * PCI_COMMAND_MEMORY, so we have to fudge the mem_flags. - */ - for (ln=b->devices.next; ln != &b->devices; ln=ln->next) { - dev = pci_dev_b(ln); - if (PCI_FUNC(dev->devfn) == 0) { - if ((PCI_SLOT(dev->devfn) == 0) || - (PCI_SLOT(dev->devfn) == 1)) { - if (pci_read_config_word(dev, PCI_COMMAND, - &command) == 0) { - command |= PCI_COMMAND_IO; - pci_write_config_word(dev, PCI_COMMAND, - command); - dev->resource[1].flags |= 1; - } - } - } - } } void __init @@ -239,7 +230,7 @@ with tons of bogus information in the pci_dev. On Origins the INTA, INTB and INTC pins are all wired together as if it'd only use INTA. */ - printk("PCI: Fixing base addresses for device %s\n", d->slot_name); + printk("PCI: Fixing base addresses for IOC3 device %s\n", d->slot_name); for (i = 1; i <= PCI_ROM_RESOURCE; i++) { d->resource[i].start = 0UL; @@ -251,8 +242,115 @@ d->irq = 1; } +static void __init +pci_fixup_isp1020(struct pci_dev *d) +{ + unsigned short command; + + printk("PCI: Fixing isp1020 in [bus:slot.fn] %s\n", d->slot_name); + + /* Configure device to allow bus mastering, i/o and memory mapping. + * Older qlogicisp driver expects to have the IO space enable + * bit set. Things stop working if we program the controllers as not having + * PCI_COMMAND_MEMORY, so we have to fudge the mem_flags. + */ + + /* only turn on scsi's on main bus */ + if (d->bus->number == 0) { + pci_set_master(d); + pci_read_config_word(d, PCI_COMMAND, &command); + command |= PCI_COMMAND_MEMORY; + command |= PCI_COMMAND_IO; + pci_write_config_word(d, PCI_COMMAND, command); + d->resource[1].flags |= 1; + } +} +static void __init +pci_fixup_isp2x00(struct pci_dev *d) +{ + unsigned int bus_id = (unsigned) d->bus->number; + bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], + bus_to_wid[bus_id]); + bridgereg_t devreg; + int i; + int slot = PCI_SLOT(d->devfn); + unsigned int start; + unsigned short command; + + printk("PCI: Fixing isp2x00 in [bus:slot.fn] %s\n", d->slot_name); + + /* set the resource struct for this device */ + start = (u32) bridge; /* yes, we want to lose the upper 32 bits here */ + start |= BRIDGE_DEVIO(slot); + + d->resource[0].start = start; + d->resource[0].end = d->resource[0].start + 0xff; + d->resource[0].flags = IORESOURCE_IO; + + d->resource[1].start = start; + d->resource[1].end = d->resource[0].start + 0xfff; + d->resource[1].flags = IORESOURCE_MEM; + + /* + * set the bridge device(x) reg for this device + */ + devreg = bridge->b_device[slot].reg; + /* point device(x) to it appropriate small window */ + devreg &= ~BRIDGE_DEV_OFF_MASK; + devreg |= (start >> 20) & BRIDGE_DEV_OFF_MASK; + + /* turn on byte swapping in direct map mode (how we currently run dma's) */ + devreg |= BRIDGE_DEV_SWAP_DIR; /* turn on byte swapping */ + + bridge->b_device[slot].reg = devreg; + + /* set card's base addr reg */ + //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x500001); + //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, 0x8b00000); + //pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, 0x8b20000); + + /* I got these from booting irix on system...*/ + pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x200001); + //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, 0xf800000); + pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, 0x10200000); + + pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, start); + //pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, (start | 0x20000)); + + + /* set cache line size */ + pci_conf0_write_config_dword(d, PCI_CACHE_LINE_SIZE, 0xf080); + + /* set pci bus timeout */ + bridge->b_bus_timeout |= BRIDGE_BUS_PCI_RETRY_HLD(0x3); + bridge->b_wid_tflush; + printk("PCI: bridge bus timeout= 0x%x \n", bridge->b_bus_timeout); + + /* set host error field */ + bridge->b_int_host_err = 0x44; + bridge->b_wid_tflush; + + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + for (i=0; i<8; i++) + printk("PCI: device(%d)= 0x%x\n",i,bridge->b_device[i].reg); + + /* configure device to allow bus mastering, i/o and memory mapping */ + pci_set_master(d); + pci_read_config_word(d, PCI_COMMAND, &command); + command |= PCI_COMMAND_MEMORY; + command |= PCI_COMMAND_IO; + pci_write_config_word(d, PCI_COMMAND, command); + /*d->resource[1].flags |= 1;*/ +} + struct pci_fixup pcibios_fixups[] = { { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, pci_fixup_ioc3 }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020, + pci_fixup_isp1020 }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100, + pci_fixup_isp2x00 }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200, + pci_fixup_isp2x00 }, { 0 } }; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-reset.c linux/arch/mips64/sgi-ip27/ip27-reset.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-reset.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/sgi-ip27/ip27-reset.c Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -/* $Id: ip27-reset.c,v 1.1 2000/01/17 23:32:47 ralf Exp $ +/* $Id$ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -9,15 +9,22 @@ * Copyright (C) 1997, 1998, 1999 by Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. */ +#include #include #include #include +#include +#include #include #include #include #include #include #include +#include +#include +#include +#include void machine_restart(char *command) __attribute__((noreturn)); void machine_halt(void) __attribute__((noreturn)); @@ -26,7 +33,19 @@ /* XXX How to pass the reboot command to the firmware??? */ void machine_restart(char *command) { - ArcReboot(); + int i; + + printk("Reboot started from CPU %d\n", smp_processor_id()); +#ifdef CONFIG_SMP + smp_send_stop(); +#endif +#if 0 + for (i = 0; i < numnodes; i++) + REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG, + PROMOP_RESTART); +#else + LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET); +#endif } void machine_halt(void) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-setup.c linux/arch/mips64/sgi-ip27/ip27-setup.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-setup.c Thu Mar 2 14:36:22 2000 +++ linux/arch/mips64/sgi-ip27/ip27-setup.c Mon May 15 12:10:26 2000 @@ -1,4 +1,4 @@ -/* $Id: ip27-setup.c,v 1.6 2000/02/05 02:12:32 kanoj Exp $ +/* $Id: ip27-setup.c,v 1.7 2000/03/07 15:45:29 ralf Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -19,12 +19,25 @@ #include #include #include +#include +#include +#include +#include +#include /* Check against user dumbness. */ #ifdef CONFIG_VT #error CONFIG_VT not allowed for IP27. #endif +#undef DEBUG_SETUP +#ifdef DEBUG_SETUP +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + + /* * get_nasid() returns the physical node id number of the caller. */ @@ -84,12 +97,130 @@ #endif } +#define XBOW_WIDGET_PART_NUM 0x0 +#define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */ +#define BASE_XBOW_PORT 8 /* Lowest external port */ + +static void __init pcibr_setup(void) +{ + int i; + bridge_t *bridge; + volatile u64 hubreg; + nasid_t nasid; + xwidget_part_num_t partnum; + widgetreg_t widget_id; + + num_bridges = 0; + /* + * find what's on our local node + */ + nasid = 0; + hubreg = LOCAL_HUB_L(IIO_LLP_CSR); + if (hubreg & IIO_LLP_CSR_IS_UP) { + /* link is up */ + widget_id = *(volatile widgetreg_t *) + (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); + partnum = XWIDGET_PART_NUM(widget_id); + printk("pcibr_setup(): found partnum= 0x%x ", partnum); + if (partnum == BRIDGE_WIDGET_PART_NUM) { + /* + * found direct connected bridge so must be Origin200 + */ + printk("...is bridge\n"); + num_bridges = 1; + bus_to_wid[0] = 0x8; + bus_to_nid[0] = 0; + } + if (partnum == XBOW_WIDGET_PART_NUM) { + lboard_t *brd; + klxbow_t *xbow_p; + /* + * found xbow, so may have multiple bridges + * need to probe xbow + */ + printk("...is xbow\n"); + + if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_MIDPLANE8)) == NULL) + printk("argh\n"); + else + printk("brd= 0x%x\n", brd); + if ((xbow_p = (klxbow_t *) + find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL) + printk("argh\n"); + else { + for (i=HUB_WIDGET_ID_MIN; i<=HUB_WIDGET_ID_MAX; i++) { + if (!XBOW_PORT_IS_ENABLED(xbow_p, i)) + continue; + if (XBOW_PORT_TYPE_IO(xbow_p, i)) { + widget_id = *(volatile widgetreg_t *) + (RAW_NODE_SWIN_BASE(nasid, i) + WIDGET_ID); + partnum = XWIDGET_PART_NUM(widget_id); + if (partnum == BRIDGE_WIDGET_PART_NUM) { + printk("widget 0x%x is a bridge\n", i); + bus_to_wid[num_bridges] = i; + bus_to_nid[num_bridges] = nasid; + num_bridges++; + } + } + } + } + } + if (partnum == XXBOW_WIDGET_PART_NUM) { + /* + * found xbridge, assume ibrick for now + */ + printk("...is xbridge\n"); + bus_to_wid[0] = 0xb; + bus_to_wid[1] = 0xe; + bus_to_wid[2] = 0xf; + + bus_to_nid[0] = 0; + bus_to_nid[1] = 0; + bus_to_nid[2] = 0; + + num_bridges = 3; + } + } + /* + * set bridge registers + */ + for (i=0; ib_int_rst_stat = (BRIDGE_IRR_ALL_CLR); + /* + * Until otherwise set up, assume all interrupts are from slot 0 + */ + bridge->b_int_device = (u32) 0x0; + /* + * swap pio's to pci mem and io space (big windows) + */ + bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP; + bridge->b_wid_control |= BRIDGE_CTRL_MEM_SWAP; + + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + } +} + void __init ip27_setup(void) { nasid_t nid; hubreg_t p, e; - set_cp0_status(ST0_IM, 0); + /* + * hub_rtc init and cpu clock intr enabled for later calibrate_delay. + */ + DBG("ip27_setup(): Entered.\n"); + per_cpu_init(); nid = get_nasid(); printk("IP27: Running on node %d.\n", nid); @@ -108,4 +239,9 @@ verify_mode(); ioc3_sio_init(); ioc3_eth_init(); + + DBG("ip27_setup(): calling pcibr_setup\n"); + /* set some bridge registers */ + pcibr_setup(); + DBG("ip27_setup(): Exit.\n"); } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-timer.c linux/arch/mips64/sgi-ip27/ip27-timer.c --- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-timer.c Thu Mar 2 14:36:22 2000 +++ linux/arch/mips64/sgi-ip27/ip27-timer.c Mon May 15 12:10:26 2000 @@ -3,6 +3,7 @@ * Copytight (C) 1999 Ralf Baechle (ralf@gnu.org) * Copytight (C) 1999 Silicon Graphics, Inc. */ +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include #include @@ -44,7 +46,6 @@ { int retval = 0; int real_seconds, real_minutes, cmos_minutes; - unsigned char save_control, save_freq_select; struct m48t35_rtc *rtc; nasid_t nid; @@ -89,20 +90,50 @@ void rt_timer_interrupt(struct pt_regs *regs) { + int cpu = smp_processor_id(); + int cpuA = ((cputoslice(smp_processor_id())) == 0); + int user = user_mode(regs); int irq = 7; /* XXX Assign number */ write_lock(&xtime_lock); again: - LOCAL_HUB_S(PI_RT_PEND_A, 0); /* Ack */ + LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */ ct_cur += CYCLES_PER_JIFFY; - LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur); + LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur); if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur) goto again; - kstat.irqs[0][irq]++; + kstat.irqs[cpu][irq]++; /* kstat+do_timer only for bootcpu? */ do_timer(regs); + +#ifdef CONFIG_SMP + if (current->pid) { + unsigned int *inc, *inc2; + + update_one_process(current, 1, user, !user, cpu); + if (--current->counter <= 0) { + current->counter = 0; + current->need_resched = 1; + } + + if (user) { + if (current->priority < DEF_PRIORITY) { + inc = &kstat.cpu_nice; + inc2 = &kstat.per_cpu_nice[cpu]; + } else { + inc = &kstat.cpu_user; + inc2 = &kstat.per_cpu_user[cpu]; + } + } else { + inc = &kstat.cpu_system; + inc2 = &kstat.per_cpu_system[cpu]; + } + atomic_inc((atomic_t *)inc); + atomic_inc((atomic_t *)inc2); + } +#endif /* CONFIG_SMP */ /* * If we have an externally synchronized Linux clock, then update @@ -194,7 +225,8 @@ nasid_t nid; nid = get_nasid(); - rtc = KL_CONFIG_CH_CONS_INFO(nid)->memory_base + IOC3_BYTEBUS_DEV0; + rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base + + IOC3_BYTEBUS_DEV0); rtc->control |= M48T35_RTC_READ; sec = rtc->sec; @@ -221,15 +253,18 @@ void __init time_init(void) { + xtime.tv_sec = get_m48t35_time(); + xtime.tv_usec = 0; +} + +void __init cpu_time_init(void) +{ lboard_t *board; klcpu_t *cpu; int cpuid; - xtime.tv_sec = get_m48t35_time(); - xtime.tv_usec = 0; - /* Don't use ARCS. ARCS is fragile. Klconfig is simple and sane. */ - board = find_lboard(KLTYPE_IP27); + board = find_lboard(KL_CONFIG_INFO(get_nasid()), KLTYPE_IP27); if (!board) panic("Can't find board info for myself."); @@ -238,15 +273,29 @@ if (!cpu) panic("No information about myself?"); - printk("CPU clock is %dMHz.\n", cpu->cpu_speed); - - /* Don't worry about second CPU, it's disabled. */ - LOCAL_HUB_S(PI_RT_EN_A, 1); - LOCAL_HUB_S(PI_PROF_EN_A, 0); - ct_cur = CYCLES_PER_JIFFY; - LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur); - LOCAL_HUB_S(PI_RT_COUNT, 0); - LOCAL_HUB_S(PI_RT_PEND_A, 0); + printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed); set_cp0_status(SRB_TIMOCLK, SRB_TIMOCLK); +} + +void __init hub_rtc_init(cnodeid_t cnode) +{ + /* + * We only need to initialize the current node. + * If this is not the current node then it is a cpuless + * node and timeouts will not happen there. + */ + if (get_compact_nodeid() == cnode) { + LOCAL_HUB_S(PI_RT_EN_A, 1); + LOCAL_HUB_S(PI_RT_EN_B, 1); + LOCAL_HUB_S(PI_PROF_EN_A, 0); + LOCAL_HUB_S(PI_PROF_EN_B, 0); + ct_cur = CYCLES_PER_JIFFY; + LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur); + LOCAL_HUB_S(PI_RT_COUNT, 0); + LOCAL_HUB_S(PI_RT_PEND_A, 0); + LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur); + LOCAL_HUB_S(PI_RT_COUNT, 0); + LOCAL_HUB_S(PI_RT_PEND_B, 0); + } } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/tools/Makefile linux/arch/mips64/tools/Makefile --- v2.3.99-pre8/linux/arch/mips64/tools/Makefile Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/tools/Makefile Sat May 13 08:30:17 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.2 1999/12/04 03:59:01 ralf Exp $ +# $Id: Makefile,v 1.1 1999/08/18 21:46:53 ralf Exp $ # # Makefile for MIPS kernel build tools. # diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/tools/offset.c linux/arch/mips64/tools/offset.c --- v2.3.99-pre8/linux/arch/mips64/tools/offset.c Sat Feb 26 22:31:41 2000 +++ linux/arch/mips64/tools/offset.c Sat May 13 08:30:17 2000 @@ -82,6 +82,7 @@ offset("#define TASK_COUNTER ", struct task_struct, counter); offset("#define TASK_PRIORITY ", struct task_struct, priority); offset("#define TASK_MM ", struct task_struct, mm); + offset("#define TASK_PROCESSOR ", struct task_struct, processor); size("#define TASK_STRUCT_SIZE ", struct task_struct); linefeed; } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/8260_io/enet.c linux/arch/ppc/8260_io/enet.c --- v2.3.99-pre8/linux/arch/ppc/8260_io/enet.c Thu May 11 15:30:06 2000 +++ linux/arch/ppc/8260_io/enet.c Mon May 15 14:53:30 2000 @@ -689,8 +689,8 @@ cep->dirty_tx = cep->cur_tx = cep->tx_bd_base; cep->cur_rx = cep->rx_bd_base; - ep->sen_genscc.scc_rfcr = SCC_EB; - ep->sen_genscc.scc_tfcr = SCC_EB; + ep->sen_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB; + ep->sen_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB; /* Set maximum bytes per receive buffer. * This appears to be an Ethernet frame size, not the buffer diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/8260_io/uart.c linux/arch/ppc/8260_io/uart.c --- v2.3.99-pre8/linux/arch/ppc/8260_io/uart.c Thu May 11 15:30:06 2000 +++ linux/arch/ppc/8260_io/uart.c Mon May 15 14:53:30 2000 @@ -2536,8 +2536,8 @@ /* Set up the uart parameters in the * parameter ram. */ - up->smc_rfcr = SMC_EB; - up->smc_tfcr = SMC_EB; + up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB; + up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB; /* Set this to 1 for now, so we get single * character interrupts. Using idle charater @@ -2579,8 +2579,8 @@ /* Set up the uart parameters in the * parameter ram. */ - sup->scc_genscc.scc_rfcr = SMC_EB; - sup->scc_genscc.scc_tfcr = SMC_EB; + sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB; + sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB; /* Set this to 1 for now, so we get single * character interrupts. Using idle charater @@ -2741,8 +2741,8 @@ */ up->smc_rbase = dp_addr; /* Base of receive buffer desc. */ up->smc_tbase = dp_addr+sizeof(cbd_t); /* Base of xmt buffer desc. */ - up->smc_rfcr = SMC_EB; - up->smc_tfcr = SMC_EB; + up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB; + up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB; /* Set this to 1 for now, so we get single character interrupts. */ diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/configs/common_defconfig linux/arch/ppc/configs/common_defconfig --- v2.3.99-pre8/linux/arch/ppc/configs/common_defconfig Thu May 11 15:30:06 2000 +++ linux/arch/ppc/configs/common_defconfig Mon May 15 14:53:30 2000 @@ -15,10 +15,11 @@ CONFIG_6xx=y # CONFIG_4xx is not set # CONFIG_PPC64 is not set -# CONFIG_82xx is not set +# CONFIG_8260 is not set # CONFIG_8xx is not set CONFIG_ALL_PPC=y # CONFIG_GEMINI is not set +# CONFIG_EST8260 is not set # CONFIG_APUS is not set # CONFIG_SMP is not set CONFIG_ALTIVEC=y @@ -159,10 +160,10 @@ # CONFIG_BLK_DEV_RZ1000 is not set CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set -# CONFIG_BLK_DEV_IDEDMA_PCI is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_IDEDMA_PCI_AUTO is not set -# CONFIG_BLK_DEV_IDEDMA is not set +CONFIG_IDEDMA_PCI_AUTO=y +CONFIG_BLK_DEV_IDEDMA=y CONFIG_IDEDMA_PCI_EXPERIMENTAL=y # CONFIG_IDEDMA_PCI_WIP is not set # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set @@ -377,6 +378,11 @@ # CONFIG_HAMRADIO is not set # +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# # ISDN subsystem # # CONFIG_ISDN is not set @@ -607,6 +613,7 @@ CONFIG_DMASOUND_AWACS=y CONFIG_DMASOUND=y # CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set # CONFIG_SOUND_ES1370 is not set # CONFIG_SOUND_ES1371 is not set # CONFIG_SOUND_ESSSOLO1 is not set @@ -688,3 +695,4 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_KGDB is not set CONFIG_XMON=y + diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/defconfig linux/arch/ppc/defconfig --- v2.3.99-pre8/linux/arch/ppc/defconfig Thu May 11 15:30:06 2000 +++ linux/arch/ppc/defconfig Mon May 15 14:53:30 2000 @@ -15,10 +15,11 @@ CONFIG_6xx=y # CONFIG_4xx is not set # CONFIG_PPC64 is not set -# CONFIG_82xx is not set +# CONFIG_8260 is not set # CONFIG_8xx is not set CONFIG_ALL_PPC=y # CONFIG_GEMINI is not set +# CONFIG_EST8260 is not set # CONFIG_APUS is not set # CONFIG_SMP is not set CONFIG_ALTIVEC=y @@ -159,10 +160,10 @@ # CONFIG_BLK_DEV_RZ1000 is not set CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set -# CONFIG_BLK_DEV_IDEDMA_PCI is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_IDEDMA_PCI_AUTO is not set -# CONFIG_BLK_DEV_IDEDMA is not set +CONFIG_IDEDMA_PCI_AUTO=y +CONFIG_BLK_DEV_IDEDMA=y CONFIG_IDEDMA_PCI_EXPERIMENTAL=y # CONFIG_IDEDMA_PCI_WIP is not set # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set @@ -377,6 +378,11 @@ # CONFIG_HAMRADIO is not set # +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# # ISDN subsystem # # CONFIG_ISDN is not set @@ -608,6 +614,7 @@ CONFIG_DMASOUND_AWACS=y CONFIG_DMASOUND=y # CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set # CONFIG_SOUND_ES1370 is not set # CONFIG_SOUND_ES1371 is not set # CONFIG_SOUND_ESSSOLO1 is not set diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c --- v2.3.99-pre8/linux/arch/ppc/kernel/chrp_pci.c Thu Feb 10 17:11:04 2000 +++ linux/arch/ppc/kernel/chrp_pci.c Mon May 15 14:53:30 2000 @@ -17,6 +17,7 @@ #include #include #include +#include #include "pci.h" @@ -31,7 +32,7 @@ * limit the bus number to 3 bits */ -int gg2_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, +int __chrp gg2_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val) { if (bus > 7) { @@ -42,7 +43,7 @@ return PCIBIOS_SUCCESSFUL; } -int gg2_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, +int __chrp gg2_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short *val) { if (bus > 7) { @@ -54,7 +55,7 @@ } -int gg2_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, +int __chrp gg2_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int *val) { if (bus > 7) { @@ -65,7 +66,7 @@ return PCIBIOS_SUCCESSFUL; } -int gg2_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, +int __chrp gg2_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char val) { if (bus > 7) @@ -74,7 +75,7 @@ return PCIBIOS_SUCCESSFUL; } -int gg2_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, +int __chrp gg2_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short val) { if (bus > 7) @@ -83,7 +84,7 @@ return PCIBIOS_SUCCESSFUL; } -int gg2_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, +int __chrp gg2_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int val) { if (bus > 7) @@ -98,7 +99,7 @@ | (((o) & ~3) << 24)) unsigned int python_busnr = 0; -int python_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, +int __chrp python_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val) { if (bus > python_busnr) { @@ -110,7 +111,7 @@ return PCIBIOS_SUCCESSFUL; } -int python_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, +int __chrp python_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short *val) { if (bus > python_busnr) { @@ -123,7 +124,7 @@ } -int python_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, +int __chrp python_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int *val) { if (bus > python_busnr) { @@ -135,7 +136,7 @@ return PCIBIOS_SUCCESSFUL; } -int python_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, +int __chrp python_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char val) { if (bus > python_busnr) @@ -145,7 +146,7 @@ return PCIBIOS_SUCCESSFUL; } -int python_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, +int __chrp python_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short val) { if (bus > python_busnr) @@ -156,7 +157,7 @@ return PCIBIOS_SUCCESSFUL; } -int python_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, +int __chrp python_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int val) { if (bus > python_busnr) @@ -167,7 +168,7 @@ } -int rtas_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, +int __chrp rtas_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char *val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); @@ -176,7 +177,7 @@ return PCIBIOS_SUCCESSFUL; } -int rtas_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, +int __chrp rtas_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short *val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); @@ -186,7 +187,7 @@ } -int rtas_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, +int __chrp rtas_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int *val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); @@ -195,7 +196,7 @@ return PCIBIOS_SUCCESSFUL; } -int rtas_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, +int __chrp rtas_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned char val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); @@ -204,7 +205,7 @@ return PCIBIOS_SUCCESSFUL; } -int rtas_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, +int __chrp rtas_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned short val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); @@ -213,7 +214,7 @@ return PCIBIOS_SUCCESSFUL; } -int rtas_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, +int __chrp rtas_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, unsigned char offset, unsigned int val) { unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c --- v2.3.99-pre8/linux/arch/ppc/kernel/chrp_setup.c Wed Apr 26 16:34:07 2000 +++ linux/arch/ppc/kernel/chrp_setup.c Mon May 15 14:53:30 2000 @@ -49,6 +49,7 @@ #include #include #include +#include #include "time.h" #include "local_irq.h" @@ -112,7 +113,7 @@ "Disabled", "Write-Through", "Copy-Back", "Transparent Mode" }; -int +int __chrp chrp_get_cpuinfo(char *buffer) { int i, len, sdramen; @@ -306,7 +307,7 @@ } } -void +void __chrp chrp_event_scan(void) { unsigned char log[1024]; @@ -317,7 +318,7 @@ ppc_md.heartbeat_count = ppc_md.heartbeat_reset; } -void +void __chrp chrp_restart(char *cmd) { printk("RTAS system-reboot returned %d\n", @@ -325,7 +326,7 @@ for (;;); } -void +void __chrp chrp_power_off(void) { /* allow power on only with power button press */ @@ -334,13 +335,13 @@ for (;;); } -void +void __chrp chrp_halt(void) { chrp_power_off(); } -u_int +u_int __chrp chrp_irq_cannonicalize(u_int irq) { if (irq == 2) @@ -353,7 +354,7 @@ } } -int chrp_get_irq( struct pt_regs *regs ) +int __chrp chrp_get_irq( struct pt_regs *regs ) { int irq; @@ -383,7 +384,7 @@ return irq; } -void chrp_post_irq(struct pt_regs* regs, int irq) +void __chrp chrp_post_irq(struct pt_regs* regs, int irq) { /* * If it's an i8259 irq then we've already done the @@ -445,7 +446,7 @@ ide_ioreg_t chrp_ide_regbase[MAX_HWIFS]; ide_ioreg_t chrp_idedma_regbase; -void +void __chrp chrp_ide_probe(void) { struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL); @@ -460,19 +461,19 @@ } } -void +void __chrp chrp_ide_insw(ide_ioreg_t port, void *buf, int ns) { ide_insw(port+_IO_BASE, buf, ns); } -void +void __chrp chrp_ide_outsw(ide_ioreg_t port, void *buf, int ns) { ide_outsw(port+_IO_BASE, buf, ns); } -int +int __chrp chrp_ide_default_irq(ide_ioreg_t base) { if (chrp_ide_ports_known == 0) @@ -480,7 +481,7 @@ return chrp_ide_irq; } -ide_ioreg_t +ide_ioreg_t __chrp chrp_ide_default_io_base(int index) { if (chrp_ide_ports_known == 0) @@ -488,13 +489,13 @@ return chrp_ide_regbase[index]; } -int +int __chrp chrp_ide_check_region(ide_ioreg_t from, unsigned int extent) { return check_region(from, extent); } -void +void __chrp chrp_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name) @@ -502,20 +503,20 @@ request_region(from, extent, name); } -void +void __chrp chrp_ide_release_region(ide_ioreg_t from, unsigned int extent) { release_region(from, extent); } -void +void __chrp chrp_ide_fix_driveid(struct hd_driveid *id) { ppc_generic_ide_fix_driveid(id); } -void +void __chrp chrp_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) { ide_ioreg_t reg = data_port; @@ -629,7 +630,7 @@ if ( ppc_md.progress ) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0); } -void +void __chrp chrp_progress(char *s, unsigned short hex) { extern unsigned int rtas_data; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/chrp_time.c linux/arch/ppc/kernel/chrp_time.c --- v2.3.99-pre8/linux/arch/ppc/kernel/chrp_time.c Fri Mar 10 16:40:40 2000 +++ linux/arch/ppc/kernel/chrp_time.c Mon May 15 14:53:30 2000 @@ -25,6 +25,7 @@ #include #include #include +#include #include "time.h" static int nvram_as1 = NVRAM_AS1; @@ -45,7 +46,7 @@ nvram_data = base + 1; } -int chrp_cmos_clock_read(int addr) +int __chrp chrp_cmos_clock_read(int addr) { if (nvram_as1 != 0) outb(addr>>8, nvram_as1); @@ -53,7 +54,7 @@ return (inb(nvram_data)); } -void chrp_cmos_clock_write(unsigned long val, int addr) +void __chrp chrp_cmos_clock_write(unsigned long val, int addr) { if (nvram_as1 != 0) outb(addr>>8, nvram_as1); @@ -65,7 +66,7 @@ /* * Set the hardware clock. -- Cort */ -int chrp_set_rtc_time(unsigned long nowtime) +int __chrp chrp_set_rtc_time(unsigned long nowtime) { unsigned char save_control, save_freq_select; struct rtc_time tm; @@ -111,7 +112,7 @@ return 0; } -unsigned long chrp_get_rtc_time(void) +unsigned long __chrp chrp_get_rtc_time(void) { unsigned int year, mon, day, hour, min, sec; int i; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S --- v2.3.99-pre8/linux/arch/ppc/kernel/entry.S Sat Feb 26 22:31:41 2000 +++ linux/arch/ppc/kernel/entry.S Mon May 15 14:53:30 2000 @@ -291,25 +291,9 @@ * -- Cort */ cmpi 0,r3,0 - bne ret_from_except - /* - * If we're returning from user mode we do things differently - * -- Cort - */ - lwz r3,_MSR(r1) - andi. r3,r3,MSR_PR - beq+ 10f - b 8f - + beq restore .globl ret_from_except ret_from_except: -0: /* disable interrupts */ - lis r30,int_control@h - ori r30,r30,int_control@l - lwz r30,0(r30) - mtlr r30 - blrl - lwz r5,_MSR(r1) andi. r5,r5,MSR_EE beq 2f @@ -341,65 +325,58 @@ bl do_softirq .globl do_bottom_half_ret do_bottom_half_ret: -2: /* disable interrupts */ - lis r30,int_control@h - ori r30,r30,int_control@l - lwz r30,0(r30) - mtlr r30 - blrl - lwz r3,_MSR(r1) /* Returning to user mode? */ +2: lwz r3,_MSR(r1) /* Returning to user mode? */ andi. r3,r3,MSR_PR - beq+ 10f /* if so, check need_resched and signals */ + beq+ restore /* if so, check need_resched and signals */ + .globl ret_to_user_hook +ret_to_user_hook: + nop lwz r3,NEED_RESCHED(r2) cmpi 0,r3,0 /* check need_resched flag */ beq+ 7f bl schedule - b 0b 7: lwz r5,SIGPENDING(r2) /* Check for pending unblocked signals */ cmpwi 0,r5,0 - beq+ 8f + beq+ restore li r3,0 addi r4,r1,STACK_FRAME_OVERHEAD bl do_signal .globl do_signal_ret do_signal_ret: - b 0b -8: /* - * We need to hard disable here even if RTL is active since - * being interrupted after here trashes the SPRG2 - * -- Cort - */ - mfmsr r0 /* Get current interrupt state */ - rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */ - mtmsr r0 /* Update machine state */ - - addi r4,r1,INT_FRAME_SIZE /* size of frame */ - stw r4,THREAD+KSP(r2) /* save kernel stack pointer */ - tophys(r3,r1) - mtspr SPRG2,r3 /* phys exception stack pointer */ - b 11f -10: /* make sure we hard disable here, even if rtl is active -- Cort */ - mfmsr r0 /* Get current interrupt state */ - rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */ - sync /* Some chip revs have problems here... */ - mtmsr r0 /* Update machine state */ -11: - lwz r2,_CTR(r1) +restore: + lwz r3,_CTR(r1) lwz r0,_LINK(r1) - mtctr r2 + mtctr r3 mtlr r0 - lwz r2,_XER(r1) - lwz r0,_CCR(r1) - mtspr XER,r2 - mtcrf 0xFF,r0 + lwz r3,_XER(r1) + mtspr XER,r3 REST_10GPRS(3, r1) REST_10GPRS(13, r1) REST_8GPRS(23, r1) REST_GPR(31, r1) - lwz r2,_NIP(r1) /* Restore environment */ + + /* make sure we hard disable here, even if rtl is active, to protect + * SRR[01] and SPRG2 -- Cort + */ + mfmsr r0 /* Get current interrupt state */ + rlwinm r0,r0,0,17,15 /* clear MSR_EE in r0 */ + sync /* Some chip revs have problems here... */ + mtmsr r0 /* Update machine state */ + + /* if returning to user mode, set new sprg2 and save kernel SP */ lwz r0,_MSR(r1) - mtspr SRR0,r2 mtspr SRR1,r0 + andi. r0,r0,MSR_PR + beq+ 1f + addi r0,r1,INT_FRAME_SIZE /* size of frame */ + stw r0,THREAD+KSP(r2) /* save kernel stack pointer */ + tophys(r2,r1) + mtspr SPRG2,r2 /* phys exception stack pointer */ +1: + lwz r2,_CCR(r1) + mtcrf 0xFF,r2 + lwz r2,_NIP(r1) + mtspr SRR0,r2 lwz r0,GPR0(r1) lwz r2,GPR2(r1) lwz r1,GPR1(r1) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S --- v2.3.99-pre8/linux/arch/ppc/kernel/head.S Thu May 11 15:30:06 2000 +++ linux/arch/ppc/kernel/head.S Mon May 15 14:53:30 2000 @@ -1459,7 +1459,8 @@ /* * Set up the segment registers for a new context. */ -_GLOBAL(set_context) + .globl set_context +set_context: rlwinm r3,r3,4,8,27 /* VSID = context << 4 */ addis r3,r3,0x6000 /* Set Ks, Ku bits */ li r0,12 /* TASK_SIZE / SEGMENT_SIZE */ diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c --- v2.3.99-pre8/linux/arch/ppc/kernel/ppc_ksyms.c Thu May 11 15:30:06 2000 +++ linux/arch/ppc/kernel/ppc_ksyms.c Mon May 15 14:53:30 2000 @@ -58,6 +58,7 @@ long long __ashldi3(long long, int); long long __lshrdi3(long long, int); int abs(int); +extern unsigned long ret_to_user_hook; EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(do_signal); @@ -284,3 +285,5 @@ EXPORT_SYMBOL(debugger_iabr_match); EXPORT_SYMBOL(debugger_dabr_match); EXPORT_SYMBOL(debugger_fault_handler); + +EXPORT_SYMBOL(ret_to_user_hook); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c --- v2.3.99-pre8/linux/arch/ppc/kernel/ptrace.c Wed Apr 26 16:34:07 2000 +++ linux/arch/ppc/kernel/ptrace.c Mon May 15 14:53:30 2000 @@ -1,7 +1,7 @@ /* * linux/arch/ppc/kernel/ptrace.c * - * PowerPC version + * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * * Derived from "arch/m68k/kernel/ptrace.c" @@ -9,14 +9,14 @@ * Taken from linux/kernel/ptrace.c and modified for M680x0. * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds * - * Modified by Cort Dougan (cort@cs.nmt.edu) + * Modified by Cort Dougan (cort@hq.fsmlabs.com) + * and Paul Mackerras (paulus@linuxcare.com.au). * * This file is subject to the terms and conditions of the GNU General * Public License. See the file README.legal in the main directory of * this archive for more details. */ -#include #include #include #include @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include #include @@ -44,7 +44,7 @@ /* * Get contents of register REGNO in task TASK. */ -static inline long get_reg(struct task_struct *task, int regno) +static inline unsigned long get_reg(struct task_struct *task, int regno) { if (regno < sizeof(struct pt_regs) / sizeof(unsigned long)) return ((unsigned long *)task->thread.regs)[regno]; @@ -64,7 +64,7 @@ ((unsigned long *)task->thread.regs)[regno] = data; return 0; } - return -1; + return -EIO; } static inline void @@ -81,216 +81,10 @@ regs->msr &= ~MSR_SE; } -#if 0 -/* - * This routine gets a long from any process space by following the page - * tables. NOTE! You should check that the long isn't on a page boundary, - * and that it is in the task area before calling this: this routine does - * no checking. - * - */ -static unsigned long get_long(struct task_struct * tsk, - struct vm_area_struct * vma, unsigned long addr) -{ - pgd_t * pgdir; - pmd_t * pgmiddle; - pte_t * pgtable; - unsigned long page; - -repeat: - pgdir = pgd_offset(vma->vm_mm, addr); - if (pgd_none(*pgdir)) { - handle_mm_fault(tsk->mm, vma, addr, 0); - goto repeat; - } - if (pgd_bad(*pgdir)) { - printk("ptrace[1]: bad page directory %lx\n", pgd_val(*pgdir)); - pgd_clear(pgdir); - return 0; - } - pgmiddle = pmd_offset(pgdir,addr); - if (pmd_none(*pgmiddle)) { - handle_mm_fault(tsk->mm, vma, addr, 0); - goto repeat; - } - if (pmd_bad(*pgmiddle)) { - printk("ptrace[3]: bad pmd %lx\n", pmd_val(*pgmiddle)); - pmd_clear(pgmiddle); - return 0; - } - pgtable = pte_offset(pgmiddle, addr); - if (!pte_present(*pgtable)) { - handle_mm_fault(tsk->mm, vma, addr, 0); - goto repeat; - } - page = pte_page(*pgtable); -/* this is a hack for non-kernel-mapped video buffers and similar */ - if (MAP_NR(page) >= max_mapnr) - return 0; - page += addr & ~PAGE_MASK; - return *(unsigned long *) page; -} - -/* - * This routine puts a long into any process space by following the page - * tables. NOTE! You should check that the long isn't on a page boundary, - * and that it is in the task area before calling this: this routine does - * no checking. - * - * Now keeps R/W state of page so that a text page stays readonly - * even if a debugger scribbles breakpoints into it. -M.U- - */ -static void put_long(struct task_struct * tsk, struct vm_area_struct * vma, - unsigned long addr, unsigned long data) -{ - pgd_t *pgdir; - pmd_t *pgmiddle; - pte_t *pgtable; - unsigned long page; - -repeat: - pgdir = pgd_offset(vma->vm_mm, addr); - if (!pgd_present(*pgdir)) { - handle_mm_fault(tsk->mm, vma, addr, 1); - goto repeat; - } - if (pgd_bad(*pgdir)) { - printk("ptrace[2]: bad page directory %lx\n", pgd_val(*pgdir)); - pgd_clear(pgdir); - return; - } - pgmiddle = pmd_offset(pgdir,addr); - if (pmd_none(*pgmiddle)) { - handle_mm_fault(tsk->mm, vma, addr, 1); - goto repeat; - } - if (pmd_bad(*pgmiddle)) { - printk("ptrace[4]: bad pmd %lx\n", pmd_val(*pgmiddle)); - pmd_clear(pgmiddle); - return; - } - pgtable = pte_offset(pgmiddle, addr); - if (!pte_present(*pgtable)) { - handle_mm_fault(tsk->mm, vma, addr, 1); - goto repeat; - } - page = pte_page(*pgtable); - if (!pte_write(*pgtable)) { - handle_mm_fault(tsk->mm, vma, addr, 1); - goto repeat; - } -/* this is a hack for non-kernel-mapped video buffers and similar */ - if (MAP_NR(page) < max_mapnr) { - unsigned long phys_addr = page + (addr & ~PAGE_MASK); - *(unsigned long *) phys_addr = data; - flush_icache_range(phys_addr, phys_addr+4); - } -/* we're bypassing pagetables, so we have to set the dirty bit ourselves */ -/* this should also re-instate whatever read-only mode there was before */ - set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot))); - flush_tlb_all(); -} - -/* - * This routine checks the page boundaries, and that the offset is - * within the task area. It then calls get_long() to read a long. - */ -static int read_long(struct task_struct * tsk, unsigned long addr, - unsigned long * result) -{ - struct vm_area_struct * vma = find_extend_vma(tsk->mm, addr); - - if (!vma) - return -EIO; - if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) { - unsigned long low,high; - struct vm_area_struct * vma_low = vma; - - if (addr + sizeof(long) >= vma->vm_end) { - vma_low = vma->vm_next; - if (!vma_low || vma_low->vm_start != vma->vm_end) - return -EIO; - } - high = get_long(tsk, vma,addr & ~(sizeof(long)-1)); - low = get_long(tsk, vma_low,(addr+sizeof(long)) & ~(sizeof(long)-1)); - switch (addr & (sizeof(long)-1)) { - case 3: - low >>= 8; - low |= high << 24; - break; - case 2: - low >>= 16; - low |= high << 16; - break; - case 1: - low >>= 24; - low |= high << 8; - break; - } - *result = low; - } else - *result = get_long(tsk, vma,addr); - return 0; -} - -/* - * This routine checks the page boundaries, and that the offset is - * within the task area. It then calls put_long() to write a long. - */ -static int write_long(struct task_struct * tsk, unsigned long addr, - unsigned long data) -{ - struct vm_area_struct * vma = find_extend_vma(tsk->mm, addr); - - if (!vma) - return -EIO; - if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) { - unsigned long low,high; - struct vm_area_struct * vma_low = vma; - - if (addr + sizeof(long) >= vma->vm_end) { - vma_low = vma->vm_next; - if (!vma_low || vma_low->vm_start != vma->vm_end) - return -EIO; - } - high = get_long(tsk, vma,addr & ~(sizeof(long)-1)); - low = get_long(tsk, vma_low,(addr+sizeof(long)) & ~(sizeof(long)-1)); - switch (addr & (sizeof(long)-1)) { - case 0: /* shouldn't happen, but safety first */ - high = data; - break; - case 3: - low &= 0x000000ff; - low |= data << 8; - high &= ~0xff; - high |= data >> 24; - break; - case 2: - low &= 0x0000ffff; - low |= data << 16; - high &= ~0xffff; - high |= data >> 16; - break; - case 1: - low &= 0x00ffffff; - low |= data << 24; - high &= ~0xffffff; - high |= data >> 8; - break; - } - put_long(tsk, vma,addr & ~(sizeof(long)-1),high); - put_long(tsk, vma_low,(addr+sizeof(long)) & ~(sizeof(long)-1),low); - } else - put_long(tsk, vma,addr,data); - return 0; -} -#endif - -asmlinkage int sys_ptrace(long request, long pid, long addr, long data) +int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; int ret = -EPERM; - unsigned long flags; lock_kernel(); if (request == PTRACE_TRACEME) { @@ -302,209 +96,209 @@ 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 ) + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) goto out; + ret = -EPERM; + if (pid == 1) /* you may not mess with init */ + goto out_tsk; + if (request == PTRACE_ATTACH) { if (child == current) - goto out; + goto out_tsk; if ((!child->dumpable || (current->uid != child->euid) || - (current->uid != child->uid) || (current->uid != child->suid) || + (current->uid != child->uid) || (current->gid != child->egid) || - (current->gid != child->gid) || (current->gid != child->sgid) || - (!cap_issubset(child->cap_permitted, current->cap_permitted))) + (!cap_issubset(child->cap_permitted, current->cap_permitted)) || + (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out; + goto out_tsk; /* the same process cannot be attached many times */ if (child->flags & PF_PTRACED) - goto out; + goto out_tsk; child->flags |= PF_PTRACED; - - write_lock_irqsave(&tasklist_lock, flags); + + write_lock_irq(&tasklist_lock); if (child->p_pptr != current) { REMOVE_LINKS(child); child->p_pptr = current; SET_LINKS(child); } - write_unlock_irqrestore(&tasklist_lock, flags); + write_unlock_irq(&tasklist_lock); send_sig(SIGSTOP, child, 1); ret = 0; - goto out; + goto out_tsk; } ret = -ESRCH; if (!(child->flags & PF_PTRACED)) - goto out; + goto out_tsk; if (child->state != TASK_STOPPED) { if (request != PTRACE_KILL) - goto out; + goto out_tsk; } if (child->p_pptr != current) - goto out; + goto out_tsk; switch (request) { /* when I and D space are separate, these will need to be fixed. */ - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: { - unsigned long tmp; - int copied; - - copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); - ret = -EIO; - if (copied != sizeof(tmp)) - goto out; - ret = put_user(tmp,(unsigned long *) data); - goto out; - } - /* read the word at location addr in the USER area. */ - case PTRACE_PEEKUSR: { - unsigned long tmp; - - if ((addr & 3) || addr < 0 || addr > (PT_FPSCR << 2)) { - ret = -EIO; - goto out; - } - - ret = verify_area(VERIFY_WRITE, (void *) data, - sizeof(long)); - if (ret) - goto out; - tmp = 0; /* Default return condition */ - addr = addr >> 2; /* temporary hack. */ - if (addr < PT_FPR0) { - tmp = get_reg(child, addr); - } - else if (addr >= PT_FPR0 && addr <= PT_FPSCR) { - if (child->thread.regs->msr & MSR_FP) - giveup_fpu(child); - tmp = ((long *)child->thread.fpr)[addr - PT_FPR0]; - } - else - ret = -EIO; - if (!ret) - put_user(tmp,(unsigned long *) data); - goto out; - } - - /* If I and D space are separate, this will have to be fixed. */ - case PTRACE_POKETEXT: /* write the word at location addr. */ - case PTRACE_POKEDATA: - ret = 0; - if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) - goto out; - ret = -EIO; - goto out; - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ - ret = -EIO; - if ((addr & 3) || addr < 0 || addr >= ((PT_FPR0 + 64) << 2)) - goto out; - - addr = addr >> 2; /* temporary hack. */ - - if (addr == PT_ORIG_R3) - goto out; - if (addr < PT_FPR0) { - if (put_reg(child, addr, data)) - goto out; - ret = 0; - goto out; - } - if (addr >= PT_FPR0 && addr < PT_FPR0 + 64) { - if (child->thread.regs->msr & MSR_FP) - giveup_fpu(child); - ((long *)child->thread.fpr)[addr - PT_FPR0] = data; - ret = 0; - goto out; - } - goto out; + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA: { + unsigned long tmp; + int copied; + + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + ret = -EIO; + if (copied != sizeof(tmp)) + break; + ret = put_user(tmp,(unsigned long *) data); + break; + } - case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: { /* restart after signal. */ - ret = -EIO; - if ((unsigned long) data >= _NSIG) - goto out; - if (request == PTRACE_SYSCALL) - child->flags |= PF_TRACESYS; - else - child->flags &= ~PF_TRACESYS; - child->exit_code = data; - wake_up_process(child); - /* make sure the single step bit is not set. */ - clear_single_step(child); + /* read the word at location addr in the USER area. */ + /* XXX this will need fixing for 64-bit */ + case PTRACE_PEEKUSR: { + unsigned long index, tmp; + + ret = -EIO; + /* convert to index and check */ + index = (unsigned long) addr >> 2; + if ((addr & 3) || index > PT_FPSCR) + break; + + if (addr < PT_FPR0) { + tmp = get_reg(child, (int) index); + } else { + if (child->thread.regs->msr & MSR_FP) + giveup_fpu(child); + tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0]; + } + ret = put_user(tmp,(unsigned long *) data); + break; + } + + /* If I and D space are separate, this will have to be fixed. */ + case PTRACE_POKETEXT: /* write the word at location addr. */ + case PTRACE_POKEDATA: + ret = 0; + if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) + break; + ret = -EIO; + break; + + /* write the word at location addr in the USER area */ + /* XXX this will need fixing for 64-bit */ + case PTRACE_POKEUSR: { + unsigned long index; + + ret = -EIO; + /* convert to index and check */ + index = (unsigned long) addr >> 2; + if ((addr & 3) || index > PT_FPSCR) + break; + + if (addr == PT_ORIG_R3) + break; + if (addr < PT_FPR0) { + ret = put_reg(child, addr, data); + } else { + if (child->thread.regs->msr & MSR_FP) + giveup_fpu(child); + ((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data; ret = 0; - goto out; } + break; + } + + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: { /* restart after signal. */ + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + if (request == PTRACE_SYSCALL) + child->flags |= PF_TRACESYS; + else + child->flags &= ~PF_TRACESYS; + child->exit_code = data; + /* make sure the single step bit is not set. */ + clear_single_step(child); + wake_up_process(child); + ret = 0; + break; + } /* * make the child exit. Best I can do is send it a sigkill. * perhaps it should be put in the status that it wants to * exit. */ - case PTRACE_KILL: { - ret = 0; - if (child->state == TASK_ZOMBIE) /* already dead */ - goto out; - wake_up_process(child); - child->exit_code = SIGKILL; - /* make sure the single step bit is not set. */ - clear_single_step(child); - goto out; - } - - case PTRACE_SINGLESTEP: { /* set the trap flag. */ - ret = -EIO; - if ((unsigned long) data >= _NSIG) - goto out; - child->flags &= ~PF_TRACESYS; - set_single_step(child); - child->exit_code = data; - /* give it a chance to run. */ - wake_up_process(child); - ret = 0; - goto out; - } + case PTRACE_KILL: { + ret = 0; + if (child->state == TASK_ZOMBIE) /* already dead */ + break; + child->exit_code = SIGKILL; + /* make sure the single step bit is not set. */ + clear_single_step(child); + wake_up_process(child); + break; + } + + case PTRACE_SINGLESTEP: { /* set the trap flag. */ + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + child->flags &= ~PF_TRACESYS; + set_single_step(child); + child->exit_code = data; + /* give it a chance to run. */ + wake_up_process(child); + ret = 0; + break; + } - case PTRACE_DETACH: { /* detach a process that was attached. */ - ret = -EIO; - if ((unsigned long) data >= _NSIG) - goto out; - child->flags &= ~(PF_PTRACED|PF_TRACESYS); - wake_up_process(child); - child->exit_code = data; - write_lock_irqsave(&tasklist_lock, flags); - REMOVE_LINKS(child); - child->p_pptr = child->p_opptr; - SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); - /* make sure the single step bit is not set. */ - clear_single_step(child); - ret = 0; - goto out; - } + case PTRACE_DETACH: { /* detach a process that was attached. */ + ret = -EIO; + if ((unsigned long) data > _NSIG) + break; + child->flags &= ~(PF_PTRACED|PF_TRACESYS); + child->exit_code = data; + write_lock_irq(&tasklist_lock); + REMOVE_LINKS(child); + child->p_pptr = child->p_opptr; + SET_LINKS(child); + write_unlock_irq(&tasklist_lock); + /* make sure the single step bit is not set. */ + clear_single_step(child); + wake_up_process(child); + ret = 0; + break; + } - default: - ret = -EIO; - goto out; + default: + ret = -EIO; + break; } +out_tsk: + free_task_struct(child); out: unlock_kernel(); return ret; } -asmlinkage void syscall_trace(void) +void syscall_trace(void) { if ((current->flags & (PF_PTRACED|PF_TRACESYS)) != (PF_PTRACED|PF_TRACESYS)) - goto out; + return; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); @@ -518,5 +312,4 @@ send_sig(current->exit_code, current, 1); current->exit_code = 0; } -out: } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c --- v2.3.99-pre8/linux/arch/ppc/kernel/setup.c Thu May 11 15:30:06 2000 +++ linux/arch/ppc/kernel/setup.c Mon May 15 11:03:48 2000 @@ -776,8 +776,11 @@ id->word127 = __le16_to_cpu(id->word127); id->dlf = __le16_to_cpu(id->dlf); id->csfo = __le16_to_cpu(id->csfo); - for (i = 0; i < 30; i++) - id->words130_159[i] = __le16_to_cpu(id->words130_159[i]); + for (i = 0; i < 26; i++) + id->words130_155[i] = __le16_to_cpu(id->words130_155[i]); + id->word156 = __le16_to_cpu(id->word156); + for (i = 0; i < 4; i++) + id->words157_159[i] = __le16_to_cpu(id->words157_159[i]); for (i = 0; i < 96; i++) id->words160_255[i] = __le16_to_cpu(id->words160_255[i]); } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c --- v2.3.99-pre8/linux/arch/ppc/kernel/time.c Wed Apr 26 16:34:07 2000 +++ linux/arch/ppc/kernel/time.c Mon May 15 14:53:30 2000 @@ -41,10 +41,7 @@ #include #include #include -/* Fixme - Why is this here? - Corey */ -#ifdef CONFIG_8xx #include -#endif #include #include "time.h" @@ -62,6 +59,7 @@ unsigned decrementer_count; /* count value for 1e6/HZ microseconds */ unsigned count_period_num; /* 1 decrementer count equals */ unsigned count_period_den; /* count_period_num / count_period_den us */ +unsigned long last_tb; /* * timer_interrupt - gets called when the decrementer overflows, @@ -103,6 +101,8 @@ */ while ((d = get_dec()) == dval) ; + asm volatile("mftb %0" : "=r" (last_tb) ); + /* * Don't play catchup between the call to time_init() * and sti() in init/main.c. @@ -149,20 +149,21 @@ */ void do_gettimeofday(struct timeval *tv) { - unsigned long flags; + unsigned long flags, diff; save_flags(flags); cli(); *tv = xtime; /* XXX we don't seem to have the decrementers synced properly yet */ #ifndef CONFIG_SMP - tv->tv_usec += (decrementer_count - get_dec()) - * count_period_num / count_period_den; - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; - } + asm volatile("mftb %0" : "=r" (diff) ); + diff -= last_tb; + + tv->tv_usec += diff * count_period_num / count_period_den; + tv->tv_sec += tv->tv_usec / 1000000; + tv->tv_usec = tv->tv_usec % 1000000; #endif + restore_flags(flags); } @@ -334,6 +335,3 @@ */ GregorianDay(tm); } - - - diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c --- v2.3.99-pre8/linux/arch/ppc/kernel/traps.c Thu May 11 15:30:06 2000 +++ linux/arch/ppc/kernel/traps.c Mon May 15 14:53:30 2000 @@ -91,7 +91,7 @@ { #if defined(CONFIG_8xx) && defined(CONFIG_PCI) /* the qspan pci read routines can cause machine checks -- Cort */ - bad_page_fault(regs,regs->dar); + bad_page_fault(regs, regs->dar); return; #endif #if defined(CONFIG_XMON) || defined(CONFIG_KGDB) @@ -214,8 +214,6 @@ { int fixed; - if (regs->msr & MSR_FP) - giveup_fpu(current); fixed = fix_alignment(regs); if (fixed == 1) { regs->nip += 4; /* skip over emulated instruction */ @@ -223,7 +221,10 @@ } if (fixed == -EFAULT) { /* fixed == -EFAULT means the operand address was bad */ - bad_page_fault(regs, regs->dar); + if (user_mode(regs)) + force_sig(SIGSEGV, current); + else + bad_page_fault(regs, regs->dar); return; } _exception(SIGBUS, regs); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mbxboot/Makefile linux/arch/ppc/mbxboot/Makefile --- v2.3.99-pre8/linux/arch/ppc/mbxboot/Makefile Thu May 11 15:30:06 2000 +++ linux/arch/ppc/mbxboot/Makefile Mon May 15 14:53:30 2000 @@ -28,14 +28,14 @@ TFTPIMAGE=/tftpboot/zImage.embedded ifdef CONFIG_8xx -ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00180000 -OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o +ZLINKFLAGS = -T vmlinux.lds -Ttext 0x00180000 +OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o gzimage.o rdimage.o CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8xx endif ifdef CONFIG_8260 -ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00400000 -OBJECTS := head_8260.o misc.o ../coffboot/zlib.o m8260_tty.o embed_config.o +ZLINKFLAGS = -T vmlinux.lds -Ttext 0x00400000 +OBJECTS := head_8260.o misc.o ../coffboot/zlib.o m8260_tty.o embed_config.o gzimage.o rdimage.o CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8260 endif @@ -61,21 +61,32 @@ all: zImage zvmlinux.initrd: zvmlinux - $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp1 $(OBJECTS) +# +# Build the boot loader images +# + $(OBJCOPY) $(OBJCOPY_ARGS) -R .gzimage gzimage.o $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ - --add-section=initrd=ramdisk.image.gz \ - --add-section=image=../coffboot/vmlinux.gz \ - zvmlinux.initrd.tmp1 zvmlinux.initrd1 - $(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd1 initrd` \ - -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd1 initrd` \ - -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd1 image` \ - -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd1 image` \ - -c -o misc.o misc.c - $(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS) + --add-section=.gzimage=../coffboot/vmlinux.gz \ + --set-section-flags=.gzimage=alloc,load,readonly,data \ + gzimage.o + $(OBJCOPY) $(OBJCOPY_ARGS) -R .rdimage rdimage.o $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ - --add-section=initrd=ramdisk.image.gz \ - --add-section=image=../coffboot/vmlinux.gz \ - zvmlinux.initrd.tmp $@ + --add-section=.rdimage=ramdisk.image.gz \ + --set-section-flags=.rdimage=alloc,load,readonly,data \ + rdimage.o + $(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS) +# +# Compute the sizes/offsets for the final image, and rebuild with these values. +# + $(CC) $(CFLAGS) \ + -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd .rdimage` \ + -DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd .rdimage` \ + -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd .gzimage` \ + -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd .gzimage` \ + -c -o misc.o misc.c + $(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment $@ + $(OBJDUMP) -h $@ zImage: zvmlinux ln -sf zvmlinux zImage @@ -85,23 +96,27 @@ zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz # -# build the boot loader image and then compute the offset into it -# for the kernel image +# Build the boot loader images +# +# + $(OBJCOPY) $(OBJCOPY_ARGS) -R .gzimage gzimage.o + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ + --add-section=.gzimage=../coffboot/vmlinux.gz \ + --set-section-flags=.gzimage=alloc,load,readonly,data \ + gzimage.o + $(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS) +# +# Compute the sizes/offsets for the final image, and rebuild with these values. # - $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \ - zvmlinux.tmp $@ -# -# then with the offset rebuild the bootloader so we know where the kernel is -# - $(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \ - -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \ - -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` \ + $(CC) $(CFLAGS) \ + -DINITRD_OFFSET=0 \ + -DINITRD_SIZE=0 \ + -DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux .gzimage` \ + -DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux .gzimage` \ -c -o misc.o misc.c - $(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS) - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \ - zvmlinux.tmp $@ - rm zvmlinux.tmp + $(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS) + $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment $@ + $(OBJDUMP) -h $@ znetboot : zImage cp zImage $(TFTPIMAGE) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mbxboot/embed_config.c linux/arch/ppc/mbxboot/embed_config.c --- v2.3.99-pre8/linux/arch/ppc/mbxboot/embed_config.c Thu May 11 15:30:06 2000 +++ linux/arch/ppc/mbxboot/embed_config.c Sun May 21 20:55:06 2000 @@ -236,12 +236,12 @@ * here for those people that may load the kernel with * a JTAG/COP tool and not the rom monitor. */ - bd->bi_baudrate = 115200; - bd->bi_intfreq = 200; - bd->bi_busfreq = 66; - bd->bi_cpmfreq = 66; - bd->bi_brgfreq = 33; - bd->bi_memsize = 16 * 1024 * 1024; + bd->bi_baudrate = 19200; + bd->bi_intfreq = 165; + bd->bi_busfreq = 33; + bd->bi_cpmfreq = 132; + bd->bi_brgfreq = bd->bi_cpmfreq / 2; /* BRGCLK = (CPM*2/4) */ + bd->bi_memsize = 16 * 1024 * 1024; #endif cp = (u_char *)def_enet_addr; @@ -250,3 +250,4 @@ } } #endif /* EST8260 */ + diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mbxboot/gzimage.c linux/arch/ppc/mbxboot/gzimage.c --- v2.3.99-pre8/linux/arch/ppc/mbxboot/gzimage.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mbxboot/gzimage.c Mon May 15 14:53:30 2000 @@ -0,0 +1,8 @@ +/* + * gzimage.c + * + * Dummy file to allow a compressed zImage to be added + * into a linker section, accessed by the boot coode + */ + +char dummy_for_gzimage; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mbxboot/head_8260.S linux/arch/ppc/mbxboot/head_8260.S --- v2.3.99-pre8/linux/arch/ppc/mbxboot/head_8260.S Thu May 11 15:30:06 2000 +++ linux/arch/ppc/mbxboot/head_8260.S Mon May 15 14:53:30 2000 @@ -9,10 +9,17 @@ * $Id: head.S,v 1.33 1999/09/08 01:06:58 cort Exp $ * * Boot loader philosophy: + * * ROM loads us to some arbitrary location - * Move the boot code to the link address (8M) + * ROM loads these registers: + * + * R3 = Pointer to the board configuration data + * R5 = Pointer to Open Firmware data + * + * ROM jumps to start/start_ + * Move the boot code to the link address (4 MB) * Call decompress_kernel() - * Relocate the initrd, zimage and residual data to 8M + * Relocate the initrd, zimage and residual data to 4 MB * Decompress the kernel to 0 * Jump to the kernel entry * -- Cort diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mbxboot/misc.c linux/arch/ppc/mbxboot/misc.c --- v2.3.99-pre8/linux/arch/ppc/mbxboot/misc.c Thu May 11 15:30:06 2000 +++ linux/arch/ppc/mbxboot/misc.c Mon May 15 14:53:30 2000 @@ -25,6 +25,15 @@ #endif /* + * The following references are needed to cause the linker to pull in the + * gzimage.o and rdimage.o files. These object files are special, + * since they get placed into the .gzimage and .rdimage ELF sections + * of the zvmlinux and zvmlinux.initrd files. + */ +extern char dummy_for_gzimage; +extern char dummy_for_rdimage; + +/* * Please send me load/board info and such data for hardware not * listed here so I can keep track since things are getting tricky * with the different load addrs with different firmware. This will diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mbxboot/rdimage.c linux/arch/ppc/mbxboot/rdimage.c --- v2.3.99-pre8/linux/arch/ppc/mbxboot/rdimage.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mbxboot/rdimage.c Mon May 15 14:53:30 2000 @@ -0,0 +1,8 @@ +/* + * rdimage.c + * + * Dummy file to allow a compressed initrd to be added + * into a linker section, accessed by the boot coode + */ + +char dummy_for_rdimage; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mbxboot/vmlinux.lds linux/arch/ppc/mbxboot/vmlinux.lds --- v2.3.99-pre8/linux/arch/ppc/mbxboot/vmlinux.lds Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mbxboot/vmlinux.lds Mon May 15 14:53:30 2000 @@ -0,0 +1,152 @@ +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } +/* .init : { *(.init) } =0*/ + .plt : { *(.plt) } + .text : + { + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.got.plt) *(.got) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + .fixup : { *(.fixup) } + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { + *(.data.init); + __vtop_table_begin = .; + *(.vtop_fixup); + __vtop_table_end = .; + __ptov_table_begin = .; + *(.ptov_fixup); + __ptov_table_end = .; + } + . = ALIGN(16); + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; + . = ALIGN(4096); + __init_end = .; + + . = ALIGN(4096); + __pmac_begin = .; + .text.pmac : { *(.text.pmac) } + .data.pmac : { *(.data.pmac) } + . = ALIGN(4096); + __pmac_end = .; + + . = ALIGN(4096); + __prep_begin = .; + .text.prep : { *(.text.prep) } + .data.prep : { *(.data.prep) } + . = ALIGN(4096); + __prep_end = .; + + . = ALIGN(4096); + __apus_begin = .; + .text.apus : { *(.text.apus) } + .data.apus : { *(.data.apus) } + . = ALIGN(4096); + __apus_end = .; + + . = ALIGN(4096); + __apus_begin = .; + .text.apus : { *(.text.apus) } + .data.apus : { *(.data.apus) } + . = ALIGN(4096); + __apus_end = .; + + . = ALIGN(4096); + __openfirmware_begin = .; + .text.openfirmware : { *(.text.openfirmware) } + .data.openfirmware : { *(.data.openfirmware) } + . = ALIGN(4096); + __openfirmware_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); + + /* + * For loader only: Put the zImage after everything else + */ + _gzstart = . ; + .gzimage : { *(.gzimage) } + _gzend = . ; + + /* + * For loader only: Put the initrd after zImage + */ + _rdstart = . ; + .rdimage : { *(.rdimage) } + _rdend = . ; + +} diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c --- v2.3.99-pre8/linux/arch/ppc/mm/fault.c Thu May 11 15:30:06 2000 +++ linux/arch/ppc/mm/fault.c Mon May 15 14:53:30 2000 @@ -62,10 +62,21 @@ { struct vm_area_struct * vma; struct mm_struct *mm = current->mm; + siginfo_t info; + int code = SEGV_MAPERR; #if defined(CONFIG_4xx) int is_write = error_code & ESR_DST; #else int is_write = error_code & 0x02000000; + + /* + * Fortunately the bit assignments in SRR1 for an instruction + * fault and DSISR for a data fault are mostly the same for the + * bits we are interested in. But there are some bits which + * indicate errors in DSISR but can validly be set in SRR1. + */ + if (regs->trap == 0x400) + error_code &= 0x48200000; #endif /* CONFIG_4xx */ #if defined(CONFIG_XMON) || defined(CONFIG_KGDB) @@ -82,16 +93,7 @@ #endif /* !CONFIG_4xx */ #endif /* CONFIG_XMON || CONFIG_KGDB */ - if (in_interrupt()) { - static int complained; - if (complained < 20) { - ++complained; - printk("page fault in interrupt handler, addr=%lx\n", - address); - show_regs(regs); - } - } - if (current == NULL || mm == NULL) { + if (in_interrupt() || mm == NULL) { bad_page_fault(regs, address); return; } @@ -107,10 +109,12 @@ goto bad_area; good_area: + code = SEGV_ACCERR; #if defined(CONFIG_6xx) if (error_code & 0x95700000) /* an error such as lwarx to I/O controller space, address matching DABR, eciwx, etc. */ + goto bad_area; #endif /* CONFIG_6xx */ #if defined(CONFIG_8xx) /* The MPC8xx seems to always set 0x80000000, which is @@ -119,9 +123,8 @@ */ if (error_code & 0x10000000) /* Guarded storage error. */ -#endif /* CONFIG_8xx */ goto bad_area; - +#endif /* CONFIG_8xx */ /* a write */ if (is_write) { @@ -135,8 +138,25 @@ if (!(vma->vm_flags & (VM_READ | VM_EXEC))) goto bad_area; } - if (!handle_mm_fault(mm, vma, address, is_write)) - goto bad_area; + + /* + * If for any reason at all we couldn't handle the fault, + * make sure we exit gracefully rather than endlessly redo + * the fault. + */ + switch (handle_mm_fault(mm, vma, address, is_write)) { + case 1: + current->min_flt++; + break; + case 2: + current->maj_flt++; + break; + case 0: + goto do_sigbus; + default: + goto out_of_memory; + } + up(&mm->mmap_sem); /* * keep track of tlb+htab misses that are good addrs but @@ -147,22 +167,55 @@ return; bad_area: - up(&mm->mmap_sem); pte_errors++; + + /* User mode accesses cause a SIGSEGV */ + if (user_mode(regs)) { + info.si_signo = SIGSEGV; + info.si_errno = 0; + info.si_code = code; + info.si_addr = (void *) address; + force_sig_info(SIGSEGV, &info, current); + return; + } + + bad_page_fault(regs, address); + return; + +/* + * We ran out of memory, or some other thing happened to us that made + * us unable to handle the page fault gracefully. + */ +out_of_memory: + up(&mm->mmap_sem); + printk("VM: killing process %s\n", current->comm); + if (user_mode(regs)) + do_exit(SIGKILL); bad_page_fault(regs, address); + return; + +do_sigbus: + up(&mm->mmap_sem); + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void *)address; + force_sig_info (SIGBUS, &info, current); + if (!user_mode(regs)) + bad_page_fault(regs, address); } +/* + * bad_page_fault is called when we have a bad access from the kernel. + * It is called from do_page_fault above and from some of the procedures + * in traps.c. + */ void bad_page_fault(struct pt_regs *regs, unsigned long address) { unsigned long fixup; - if (user_mode(regs)) { - force_sig(SIGSEGV, current); - return; - } - /* Are we prepared to handle this fault? */ if ((fixup = search_exception_table(regs->nip)) != 0) { regs->nip = fixup; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.3.99-pre8/linux/arch/ppc/mm/init.c Thu May 11 15:30:06 2000 +++ linux/arch/ppc/mm/init.c Mon May 15 14:53:30 2000 @@ -83,6 +83,7 @@ extern char etext[], _stext[]; extern char __init_begin, __init_end; extern char __prep_begin, __prep_end; +extern char __chrp_begin, __chrp_end; extern char __pmac_begin, __pmac_end; extern char __apus_begin, __apus_end; extern char __openfirmware_begin, __openfirmware_end; @@ -777,7 +778,7 @@ unsigned long a; unsigned long num_freed_pages = 0, num_prep_pages = 0, num_pmac_pages = 0, num_openfirmware_pages = 0, - num_apus_pages = 0; + num_apus_pages = 0, num_chrp_pages = 0; #define FREESEC(START,END,CNT) do { \ a = (unsigned long)(&START); \ for (; a < (unsigned long)(&END); a += PAGE_SIZE) { \ @@ -794,6 +795,7 @@ case _MACH_Pmac: FREESEC(__apus_begin,__apus_end,num_apus_pages); FREESEC(__prep_begin,__prep_end,num_prep_pages); + FREESEC(__chrp_begin,__chrp_end,num_chrp_pages); break; case _MACH_chrp: FREESEC(__apus_begin,__apus_end,num_apus_pages); @@ -803,20 +805,24 @@ case _MACH_prep: FREESEC(__apus_begin,__apus_end,num_apus_pages); FREESEC(__pmac_begin,__pmac_end,num_pmac_pages); + FREESEC(__chrp_begin,__chrp_end,num_chrp_pages); break; case _MACH_mbx: FREESEC(__apus_begin,__apus_end,num_apus_pages); FREESEC(__pmac_begin,__pmac_end,num_pmac_pages); FREESEC(__prep_begin,__prep_end,num_prep_pages); + FREESEC(__chrp_begin,__chrp_end,num_chrp_pages); break; case _MACH_apus: FREESEC(__pmac_begin,__pmac_end,num_pmac_pages); FREESEC(__prep_begin,__prep_end,num_prep_pages); + FREESEC(__chrp_begin,__chrp_end,num_chrp_pages); break; case _MACH_gemini: FREESEC(__apus_begin,__apus_end,num_apus_pages); FREESEC(__pmac_begin,__pmac_end,num_pmac_pages); FREESEC(__prep_begin,__prep_end,num_prep_pages); + FREESEC(__chrp_begin,__chrp_end,num_chrp_pages); break; } @@ -829,6 +835,8 @@ if ( num_prep_pages ) printk(" %ldk prep", PGTOKB(num_prep_pages)); + if ( num_chrp_pages ) + printk(" %ldk chrp", PGTOKB(num_chrp_pages)); if ( num_pmac_pages ) printk(" %ldk pmac", PGTOKB(num_pmac_pages)); if ( num_openfirmware_pages ) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/treeboot/mkevimg linux/arch/ppc/treeboot/mkevimg --- v2.3.99-pre8/linux/arch/ppc/treeboot/mkevimg Tue Dec 7 09:32:42 1999 +++ linux/arch/ppc/treeboot/mkevimg Mon May 15 14:53:30 2000 @@ -1,4 +1,4 @@ -#!/usr/local/bin/perl +#!/usr/bin/perl # # Copyright (c) 1998-1999 TiVo, Inc. diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/treeboot/mkirimg linux/arch/ppc/treeboot/mkirimg --- v2.3.99-pre8/linux/arch/ppc/treeboot/mkirimg Tue Dec 7 09:32:42 1999 +++ linux/arch/ppc/treeboot/mkirimg Mon May 15 14:53:30 2000 @@ -1,4 +1,4 @@ -#!/usr/local/bin/perl +#!/usr/bin/perl # # Copyright (c) 1998-1999 TiVo, Inc. # Original ELF parsing code. @@ -332,7 +332,7 @@ syswrite(OUTPUT, $ibuf, $initialOffset); if ($imageFound) { - $testN = pack ("I2", $bss_addr + $bss_size, $image_size); + $testN = pack ("N2", $bss_addr + $bss_size, $image_size); syswrite(OUTPUT, $testN, length($testN)); printf("Updated symbol \"imageSect_start\" to 0x%08x\n", $bss_addr + $bss_size); @@ -342,7 +342,7 @@ } if ($initrdFound) { - $testN = pack ("I2", $bss_addr + $bss_size + $image_size, $initrd_size); + $testN = pack ("N2", $bss_addr + $bss_size + $image_size, $initrd_size); syswrite(OUTPUT, $testN, length($testN)); printf("Updated symbol \"initrdSect_start\" to 0x%08x\n", $bss_addr + $bss_size + $image_size); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/vmlinux.lds linux/arch/ppc/vmlinux.lds --- v2.3.99-pre8/linux/arch/ppc/vmlinux.lds Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/vmlinux.lds Mon May 15 14:53:30 2000 @@ -104,6 +104,13 @@ __prep_end = .; . = ALIGN(4096); + __chrp_begin = .; + .text.chrp : { *(.text.chrp) } + .data.chrp : { *(.data.chrp) } + . = ALIGN(4096); + __chrp_end = .; + + . = ALIGN(4096); __apus_begin = .; .text.apus : { *(.text.apus) } .data.apus : { *(.data.apus) } @@ -135,4 +142,3 @@ _end = . ; PROVIDE (end = .); } - diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/config.in linux/arch/sh/config.in --- v2.3.99-pre8/linux/arch/sh/config.in Tue Apr 11 15:09:14 2000 +++ linux/arch/sh/config.in Sat May 20 12:05:29 2000 @@ -15,6 +15,10 @@ mainmenu_option next_comment comment 'Processor type and features' +choice 'SuperH system type' \ + "Generic CONFIG_SH_GENERIC \ + SolutionEngine CONFIG_SH_SOLUTION_ENGINE" Generic + choice 'Processor type' \ "SH7708 CONFIG_CPU_SUBTYPE_SH7708 \ SH7709 CONFIG_CPU_SUBTYPE_SH7709 \ @@ -32,7 +36,12 @@ define_bool CONFIG_CPU_SH4 y fi bool 'Little Endian' CONFIG_LITTLE_ENDIAN -hex 'Physical memory start address' CONFIG_MEMORY_START 08000000 +if [ "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then + define_hex CONFIG_MEMORY_START 0c000000 +else + hex 'Physical memory start address' CONFIG_MEMORY_START 08000000 + hex 'I/O port offset address' CONFIG_IOPORT_START ba000000 +fi endmenu mainmenu_option next_comment @@ -52,7 +61,9 @@ bool 'Networking support' CONFIG_NET -bool 'Directy Connected Compact Flash support' CONFIG_CF_ENABLER +if [ "$CONFIG_SH_SOLUTION_ENGINE" != "y" ]; then + bool 'Directly Connected Compact Flash support' CONFIG_CF_ENABLER +fi bool 'PCI support' CONFIG_PCI if [ "$CONFIG_PCI" = "y" ]; then diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/defconfig linux/arch/sh/defconfig --- v2.3.99-pre8/linux/arch/sh/defconfig Thu May 11 15:30:06 2000 +++ linux/arch/sh/defconfig Sat May 20 12:05:29 2000 @@ -12,6 +12,8 @@ # # Processor type and features # +CONFIG_SH_GENERIC=y +# CONFIG_SH_SOLUTION_ENGINE is not set CONFIG_CPU_SUBTYPE_SH7708=y # CONFIG_CPU_SUBTYPE_SH7709 is not set # CONFIG_CPU_SUBTYPE_SH7750 is not set @@ -19,6 +21,7 @@ # CONFIG_CPU_SH4 is not set CONFIG_LITTLE_ENDIAN=y CONFIG_MEMORY_START=0c000000 +CONFIG_IOPORT_START=ba000000 # # Loadable module support @@ -62,9 +65,10 @@ # # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set -# CONFIG_MD_STRIPED is not set +# CONFIG_MD_RAID0 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_INITRD=y @@ -85,6 +89,13 @@ # CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set # CONFIG_BLK_DEV_IDECS is not set # CONFIG_BLK_DEV_IDECD is not set # CONFIG_BLK_DEV_IDETAPE is not set @@ -137,6 +148,7 @@ # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/Makefile linux/arch/sh/kernel/Makefile --- v2.3.99-pre8/linux/arch/sh/kernel/Makefile Wed Apr 26 16:34:07 2000 +++ linux/arch/sh/kernel/Makefile Sat May 20 12:05:29 2000 @@ -10,7 +10,7 @@ $(CC) $(AFLAGS) -traditional -c $< -o $*.o O_TARGET := kernel.o -O_OBJS := process.o signal.o entry.o traps.o irq.o irq_onchip.o \ +O_OBJS := process.o signal.o entry.o traps.o irq.o irq_ipr.o \ ptrace.o setup.o time.o sys_sh.o semaphore.o pci-sh.o \ irq_imask.o OX_OBJS := sh_ksyms.o @@ -18,6 +18,14 @@ ifdef CONFIG_CF_ENABLER O_OBJS += cf-enabler.o +endif + +ifdef CONFIG_SH_GENERIC +O_OBJS += io_generic.o +endif + +ifdef CONFIG_SH_SOLUTION_ENGINE +O_OBJS += setup_se.o io_se.o endif ifdef CONFIG_CPU_SH4 diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/entry.S linux/arch/sh/kernel/entry.S --- v2.3.99-pre8/linux/arch/sh/kernel/entry.S Wed Apr 26 16:34:07 2000 +++ linux/arch/sh/kernel/entry.S Sat May 20 12:05:29 2000 @@ -282,7 +282,7 @@ mov $r0, $r9 #endif ! New Syscall ABI - sub $r9, $r8 + add #-0x40, $r8 shlr2 $r8 shll8 $r8 shll8 $r8 @@ -492,7 +492,16 @@ mov.l 2f, $k1 and $k1, $k2 ! Mask orignal SR value or $k0, $k2 ! Inherit current FD-bit - or $g_imask, $k2 ! Inherit the IMASK-bits + ! + mov $k3, $k0 ! Calculate IMASK-bits + shlr2 $k0 + and #0x3c, $k0 + cmp/eq #0x3c, $k0 + bf/s 7f + mov $g_imask, $k0 + shll2 $k0 + ! +7: or $k0, $k2 ! Set the IMASK-bits ldc $k2, $ssr ! #if defined(__SH4__) @@ -507,7 +516,7 @@ ! There's the case we don't get FPU now stc $sr, $k2 tst $k1, $k2 - bt 7f + bt 8f ! We need to grab FPU here xor $k1, $k2 ldc $k2, $sr ! Grab FPU @@ -519,7 +528,7 @@ ! ! Restoring FPU... ! -7: mov.l 3f, $k1 +8: mov.l 3f, $k1 lds $k1, $fpscr fmov.s @$r15+, $fr0 fmov.s @$r15+, $fr1 diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/io_generic.c linux/arch/sh/kernel/io_generic.c --- v2.3.99-pre8/linux/arch/sh/kernel/io_generic.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/io_generic.c Sat May 20 12:05:29 2000 @@ -0,0 +1,99 @@ +/* $Id: io_generic.c,v 1.3 2000/05/07 23:31:58 gniibe Exp $ + * + * linux/arch/sh/kernel/io_generic.c + * + * Copyright (C) 2000 Niibe Yutaka + * + * Generic I/O routine. + * + */ + +#include +#include + +#define PORT2ADDR(x) (CONFIG_IOPORT_START+(x)) + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); +} + +unsigned long inb(unsigned int port) +{ + return *(volatile unsigned char*)PORT2ADDR(port); +} + +unsigned long inb_p(unsigned int port) +{ + unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); + + delay(); + return v; +} + +unsigned long inw(unsigned int port) +{ + return *(volatile unsigned short*)PORT2ADDR(port); +} + +unsigned long inl(unsigned int port) +{ + return *(volatile unsigned long*)PORT2ADDR(port); +} + +void insb(unsigned int port, void *buffer, unsigned long count) +{ + unsigned char *buf=buffer; + while(count--) *buf++=inb(port); +} + +void insw(unsigned int port, void *buffer, unsigned long count) +{ + unsigned short *buf=buffer; + while(count--) *buf++=inw(port); +} + +void insl(unsigned int port, void *buffer, unsigned long count) +{ + unsigned long *buf=buffer; + while(count--) *buf++=inl(port); +} + +void outb(unsigned long b, unsigned int port) +{ + *(volatile unsigned char*)PORT2ADDR(port) = b; +} + +void outb_p(unsigned long b, unsigned int port) +{ + *(volatile unsigned char*)PORT2ADDR(port) = b; + delay(); +} + +void outw(unsigned long b, unsigned int port) +{ + *(volatile unsigned short*)PORT2ADDR(port) = b; +} + +void outl(unsigned long b, unsigned int port) +{ + *(volatile unsigned long*)PORT2ADDR(port) = b; +} + +void outsb(unsigned int port, const void *buffer, unsigned long count) +{ + const unsigned char *buf=buffer; + while(count--) outb(*buf++, port); +} + +void outsw(unsigned int port, const void *buffer, unsigned long count) +{ + const unsigned short *buf=buffer; + while(count--) outw(*buf++, port); +} + +void outsl(unsigned int port, const void *buffer, unsigned long count) +{ + const unsigned long *buf=buffer; + while(count--) outl(*buf++, port); +} diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/io_se.c linux/arch/sh/kernel/io_se.c --- v2.3.99-pre8/linux/arch/sh/kernel/io_se.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/io_se.c Sun May 21 20:55:06 2000 @@ -0,0 +1,221 @@ +/* $Id: io_se.c,v 1.4 2000/05/07 23:31:58 gniibe Exp $ + * + * linux/arch/sh/kernel/io_se.c + * + * Copyright (C) 2000 Kazumoto Kojima + * + * I/O routine for Hitachi SolutionEngine. + * + */ +#include +#include +#include +#include + +/* SH pcmcia io window base, start and end. */ +int sh_pcic_io_wbase = 0xb8400000; +int sh_pcic_io_start; +int sh_pcic_io_stop; +int sh_pcic_io_type; +int sh_pcic_io_dummy; + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); +} + +/* MS7750 requires special versions of in*, out* routines, since + PC-like io ports are located at upper half byte of 16-bit word which + can be accessed only with 16-bit wide. */ + +static inline volatile __u16 * +port2adr(unsigned int port) +{ + if (port >= 0x2000) + return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); + else if (port >= 0x1000) + return (volatile __u16 *) (PA_83902 + (port << 1)); + else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) + return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1)); + else + return (volatile __u16 *) (PA_SUPERIO + (port << 1)); +} + +static inline int +shifted_port(unsigned int port) +{ + /* For IDE registers, value is not shifted */ + if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6) + return 0; + else + return 1; +} + +#define maybebadio(name,port) \ + printk("bad PC-like io %s for port 0x%x at 0x%08x\n", \ + #name, (port), (__u32) __builtin_return_address(0)) + +unsigned long inb(unsigned int port) +{ + if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) + return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); + else if (shifted_port(port)) + return (*port2adr(port) >> 8); + else + return (*port2adr(port))&0xff; +} + +unsigned long inb_p(unsigned int port) +{ + unsigned long v; + + if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) + v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); + else if (shifted_port(port)) + v = (*port2adr(port) >> 8); + else + v = (*port2adr(port))&0xff; + delay(); + return v; +} + +unsigned long inw(unsigned int port) +{ + if (port >= 0x2000 || + (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)) + return *port2adr(port); + else + maybebadio(inw, port); + return 0; +} + +unsigned long inl(unsigned int port) +{ + maybebadio(inl, port); + return 0; +} + +void outb(unsigned long value, unsigned int port) +{ + if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) + *(__u8 *)(sh_pcic_io_wbase + port) = value; + else if (shifted_port(port)) + *(port2adr(port)) = value << 8; + else + *(port2adr(port)) = value; +} + +void outb_p(unsigned long value, unsigned int port) +{ + if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) + *(__u8 *)(sh_pcic_io_wbase + port) = value; + else if (shifted_port(port)) + *(port2adr(port)) = value << 8; + else + *(port2adr(port)) = value; + delay(); +} + +void outw(unsigned long value, unsigned int port) +{ + if (port >= 0x2000 || + (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)) + *port2adr(port) = value; + else + maybebadio(outw, port); +} + +void outl(unsigned long value, unsigned int port) +{ + maybebadio(outl, port); +} + +void insb(unsigned int port, void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + + if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) { + volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port); + while (count--) + *((__u8 *) addr)++ = *bp; + } else if (shifted_port(port)) { + while (count--) + *((__u8 *) addr)++ = *p >> 8; + } else { + while (count--) + *((__u8 *) addr)++ = *p; + } +} + +void insw(unsigned int port, void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + while (count--) + *((__u16 *) addr)++ = *p; +} + +void insl(unsigned int port, void *addr, unsigned long count) +{ + maybebadio(insl, port); +} + +void outsb(unsigned int port, const void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + + if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) { + volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port); + while (count--) + *bp = *((__u8 *) addr)++; + } else if (shifted_port(port)) { + while (count--) + *p = *((__u8 *) addr)++ << 8; + } else { + while (count--) + *p = *((__u8 *) addr)++; + } +} + +void outsw(unsigned int port, const void *addr, unsigned long count) +{ + volatile __u16 *p = port2adr(port); + while (count--) + *p = *((__u16 *) addr)++; +} + +void outsl(unsigned int port, const void *addr, unsigned long count) +{ + maybebadio(outsw, port); +} + +/* Map ISA bus address to the real address. Only for PCMCIA. */ + +/* ISA page descriptor. */ +static __u32 sh_isa_memmap[256]; + +int +sh_isa_mmap(__u32 start, __u32 length, __u32 offset) +{ + int idx; + + if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000)) + return -1; + + idx = start >> 12; + sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff); +#if 0 + printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n", + start, length, offset, idx, sh_isa_memmap[idx]); +#endif + return 0; +} + +unsigned long +sh_isa_slot(unsigned long offset) +{ + int idx; + + idx = (offset >> 12) & 0xff; + offset &= 0xfff; + return sh_isa_memmap[idx] + offset; +} diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/irq.c linux/arch/sh/kernel/irq.c --- v2.3.99-pre8/linux/arch/sh/kernel/irq.c Wed Apr 26 16:34:07 2000 +++ linux/arch/sh/kernel/irq.c Sun May 21 20:55:06 2000 @@ -13,6 +13,7 @@ * Naturally it's not a 1:1 relation, but there are similarities. */ +#include #include #include #include @@ -300,7 +301,7 @@ desc->handler->end(irq); spin_unlock(&irq_controller_lock); -#if 1 +#if 0 __sti(); #endif if (softirq_state[cpu].active&softirq_state[cpu].mask) @@ -513,3 +514,10 @@ spin_unlock_irqrestore(&irq_controller_lock,flags); return 0; } + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL) + +void init_irq_proc(void) +{ +} +#endif diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/irq_ipr.c linux/arch/sh/kernel/irq_ipr.c --- v2.3.99-pre8/linux/arch/sh/kernel/irq_ipr.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/irq_ipr.c Sat May 20 12:05:29 2000 @@ -0,0 +1,171 @@ +/* $Id: irq_ipr.c,v 1.6 2000/05/14 08:41:25 gniibe Exp $ + * + * linux/arch/sh/kernel/irq_ipr.c + * + * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi + * Copyright (C) 2000 Kazumoto Kojima + * + * Interrupt handling for IPR-based IRQ. + * + * Supported system: + * On-chip supporting modules (TMU, RTC, etc.). + * On-chip supporting modules for SH7709/SH7709A/SH7729. + * Hitachi SolutionEngine external I/O: + * MS7709SE01, MS7709ASE01, and MS7750SE01 + * + */ + +#include +#include +#include + +#include +#include + +struct ipr_data { + unsigned int addr; /* Address of Interrupt Priority Register */ + int shift; /* Shifts of the 16-bit data */ + int priority; /* The priority */ +}; +static struct ipr_data ipr_data[NR_IRQS]; + +void set_ipr_data(unsigned int irq, unsigned int addr, int pos, int priority) +{ + ipr_data[irq].addr = addr; + ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */ + ipr_data[irq].priority = priority; +} + +static void enable_ipr_irq(unsigned int irq); +void disable_ipr_irq(unsigned int irq); + +/* shutdown is same as "disable" */ +#define shutdown_ipr_irq disable_ipr_irq + +static void mask_and_ack_ipr(unsigned int); +static void end_ipr_irq(unsigned int irq); + +static unsigned int startup_ipr_irq(unsigned int irq) +{ + enable_ipr_irq(irq); + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type ipr_irq_type = { + "IPR-based-IRQ", + startup_ipr_irq, + shutdown_ipr_irq, + enable_ipr_irq, + disable_ipr_irq, + mask_and_ack_ipr, + end_ipr_irq +}; + +void disable_ipr_irq(unsigned int irq) +{ + unsigned long val, flags; + unsigned int addr = ipr_data[irq].addr; + unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift); + + /* Set the priority in IPR to 0 */ + save_and_cli(flags); + val = ctrl_inw(addr); + val &= mask; + ctrl_outw(val, addr); + restore_flags(flags); +} + +static void enable_ipr_irq(unsigned int irq) +{ + unsigned long val, flags; + unsigned int addr = ipr_data[irq].addr; + int priority = ipr_data[irq].priority; + unsigned short value = (priority << ipr_data[irq].shift); + + /* Set priority in IPR back to original value */ + save_and_cli(flags); + val = ctrl_inw(addr); + val |= value; + ctrl_outw(val, addr); + restore_flags(flags); +} + +void make_ipr_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &ipr_irq_type; + disable_ipr_irq(irq); +} + +static void mask_and_ack_ipr(unsigned int irq) +{ + disable_ipr_irq(irq); + +#ifdef CONFIG_CPU_SUBTYPE_SH7709 + /* This is needed when we use edge triggered setting */ + /* XXX: Is it really needed? */ + if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) { + /* Clear external interrupt request */ + int a = ctrl_inb(INTC_IRR0); + a &= ~(1 << (irq - IRQ0_IRQ)); + ctrl_outb(a, INTC_IRR0); + } +#endif +} + +static void end_ipr_irq(unsigned int irq) +{ + enable_ipr_irq(irq); +} + +void __init init_IRQ(void) +{ + int i; + + for (i = TIMER_IRQ; i < NR_IRQS; i++) { + irq_desc[i].handler = &ipr_irq_type; + } + + set_ipr_data(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); + set_ipr_data(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); + +#ifdef CONFIG_CPU_SUBTYPE_SH7709 + /* + * Initialize the Interrupt Controller (INTC) + * registers to their power on values + */ +#if 0 + /* + * XXX: I think that this is the job of boot loader. -- gniibe + * + * When Takeshi released new boot loader following setting + * will be removed shortly. + */ + ctrl_outb(0, INTC_IRR0); + ctrl_outb(0, INTC_IRR1); + ctrl_outb(0, INTC_IRR2); + + ctrl_outw(0, INTC_ICR0); + ctrl_outw(0, INTC_ICR1);/* Really? 0x4000?*/ + ctrl_outw(0, INTC_ICR2); + ctrl_outw(0, INTC_INTER); + ctrl_outw(0, INTC_IPRA); + ctrl_outw(0, INTC_IPRB); + ctrl_outw(0, INTC_IPRC); + ctrl_outw(0, INTC_IPRD); + ctrl_outw(0, INTC_IPRE); +#endif + + /* + * Enable external irq (INTC IRQ mode). + * You should set corresponding bits of PFC to "00" + * to enable these interrupts. + */ + set_ipr_data(IRQ0_IRQ, IRQ0_IRP_ADDR, IRQ0_IRP_POS, IRQ0_PRIORITY); + set_ipr_data(IRQ1_IRQ, IRQ1_IRP_ADDR, IRQ1_IRP_POS, IRQ1_PRIORITY); + set_ipr_data(IRQ2_IRQ, IRQ2_IRP_ADDR, IRQ2_IRP_POS, IRQ2_PRIORITY); + set_ipr_data(IRQ3_IRQ, IRQ3_IRP_ADDR, IRQ3_IRP_POS, IRQ3_PRIORITY); + set_ipr_data(IRQ4_IRQ, IRQ4_IRP_ADDR, IRQ4_IRP_POS, IRQ4_PRIORITY); + set_ipr_data(IRQ5_IRQ, IRQ5_IRP_ADDR, IRQ5_IRP_POS, IRQ5_PRIORITY); +#endif /* CONFIG_CPU_SUBTYPE_SH7709 */ +} diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/irq_onchip.c linux/arch/sh/kernel/irq_onchip.c --- v2.3.99-pre8/linux/arch/sh/kernel/irq_onchip.c Wed Apr 26 16:34:07 2000 +++ linux/arch/sh/kernel/irq_onchip.c Wed Dec 31 16:00:00 1969 @@ -1,298 +0,0 @@ -/* $Id: irq_onchip.c,v 1.7 2000-01-09 15:55:55+09 gniibe Exp $ - * - * linux/arch/sh/kernel/irq_onchip.c - * - * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi - * - * Interrupt handling for on-chip supporting modules (TMU, RTC, etc.). - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -struct ipr_data { - int offset; - int priority; -}; -static struct ipr_data ipr_data[NR_IRQS-TIMER_IRQ]; - -void set_ipr_data(unsigned int irq, int offset, int priority) -{ - ipr_data[irq-TIMER_IRQ].offset = offset; - ipr_data[irq-TIMER_IRQ].priority = priority; -} - -static void enable_onChip_irq(unsigned int irq); -void disable_onChip_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_onChip_irq disable_onChip_irq - -static void mask_and_ack_onChip(unsigned int); -static void end_onChip_irq(unsigned int irq); - -static unsigned int startup_onChip_irq(unsigned int irq) -{ - enable_onChip_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type onChip_irq_type = { - "On-Chip-IPR", - startup_onChip_irq, - shutdown_onChip_irq, - enable_onChip_irq, - disable_onChip_irq, - mask_and_ack_onChip, - end_onChip_irq -}; - -/* - * These have to be protected by the irq controller spinlock - * before being called. - * - * - * IPRA 15-12 11-8 7-4 3-0 - * IPRB 15-12 11-8 7-4 3-0 - * IPRC 15-12 11-8 7-4 3-0 - * - */ -#if defined(__sh3__) -#define INTC_IPR 0xfffffee2UL /* Word access */ -#define INTC_SIZE 0x2 -#elif defined(__SH4__) -#define INTC_IPR 0xffd00004UL /* Word access */ -#define INTC_SIZE 0x4 -#endif - -void disable_onChip_irq(unsigned int irq) -{ - unsigned long val, flags; - /* Set priority in IPR to 0 */ - int offset = ipr_data[irq-TIMER_IRQ].offset; - unsigned long intc_ipr_address = INTC_IPR + (offset/16*INTC_SIZE); - unsigned short mask = 0xffff ^ (0xf << (offset%16)); - - save_and_cli(flags); - val = ctrl_inw(intc_ipr_address); - val &= mask; - ctrl_outw(val, intc_ipr_address); - restore_flags(flags); -} - -static void enable_onChip_irq(unsigned int irq) -{ - unsigned long val, flags; - /* Set priority in IPR back to original value */ - int offset = ipr_data[irq-TIMER_IRQ].offset; - int priority = ipr_data[irq-TIMER_IRQ].priority; - unsigned long intc_ipr_address = INTC_IPR + (offset/16*INTC_SIZE); - unsigned short value = (priority << (offset%16)); - - save_and_cli(flags); - val = ctrl_inw(intc_ipr_address); - val |= value; - ctrl_outw(val, intc_ipr_address); - restore_flags(flags); -} - -void make_onChip_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].handler = &onChip_irq_type; - enable_irq(irq); -} - -static void mask_and_ack_onChip(unsigned int irq) -{ - disable_onChip_irq(irq); -} - -static void end_onChip_irq(unsigned int irq) -{ - enable_onChip_irq(irq); -} - - -#ifdef CONFIG_CPU_SUBTYPE_SH7709 -/* - * SH7707/SH7709/SH7709A/SH7729 Extended on-chip I/O - */ - -#define INTC_IRR0 0xa4000004UL -#define INTC_IRR1 0xa4000006UL -#define INTC_IRR2 0xa4000008UL - -#define INTC_ICR0 0xfffffee0 -#define INTC_ICR1 0xa4000010 -#define INTC_ICR2 0xa4000012 -#define INTC_INTER 0xa4000014 -#define INTC_IPRA 0xfffffee2 -#define INTC_IPRB 0xfffffee4 -#define INTC_IPRC 0xa4000016 -#define INTC_IPRD 0xa4000018 -#define INTC_IPRE 0xa400001a - -#define IRQ0_IRQ 32 -#define IRQ1_IRQ 33 -#define IRQ2_IRQ 34 -#define IRQ3_IRQ 35 -#define IRQ4_IRQ 36 -#define IRQ5_IRQ 37 - -#define IRQ0_IRP_OFFSET 32 -#define IRQ1_IRP_OFFSET 36 -#define IRQ2_IRP_OFFSET 40 -#define IRQ3_IRP_OFFSET 44 -#define IRQ4_IRP_OFFSET 48 -#define IRQ5_IRP_OFFSET 52 - -#define IRQ0_PRIORITY 1 -#define IRQ1_PRIORITY 1 -#define IRQ2_PRIORITY 1 -#define IRQ3_PRIORITY 1 -#define IRQ4_PRIORITY 1 -#define IRQ5_PRIORITY 1 - -static void enable_onChip2_irq(unsigned int irq); -void disable_onChip2_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_onChip2_irq disable_onChip2_irq - -static void mask_and_ack_onChip2(unsigned int); -static void end_onChip2_irq(unsigned int irq); - -static unsigned int startup_onChip2_irq(unsigned int irq) -{ - enable_onChip2_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type onChip2_irq_type = { - "Extended-IPR", - startup_onChip2_irq, - shutdown_onChip2_irq, - enable_onChip2_irq, - disable_onChip2_irq, - mask_and_ack_onChip2, - end_onChip2_irq -}; - -void disable_onChip2_irq(unsigned int irq) -{ - unsigned long val, flags; - /* Set priority in IPR to 0 */ - int offset = ipr_data[irq-TIMER_IRQ].offset - 32; - unsigned long intc_ipr_address = INTC_IPRC + (offset/16*INTC_SIZE); - unsigned short mask = 0xffff ^ (0xf << (offset%16)); - - save_and_cli(flags); - val = ctrl_inw(intc_ipr_address); - val &= mask; - ctrl_outw(val, intc_ipr_address); - restore_flags(flags); -} - -static void enable_onChip2_irq(unsigned int irq) -{ - unsigned long val, flags; - /* Set priority in IPR back to original value */ - int offset = ipr_data[irq-TIMER_IRQ].offset - 32; - int priority = ipr_data[irq-TIMER_IRQ].priority; - unsigned long intc_ipr_address = INTC_IPRC + (offset/16*INTC_SIZE); - unsigned short value = (priority << (offset%16)); - - save_and_cli(flags); - val = ctrl_inw(intc_ipr_address); - val |= value; - ctrl_outw(val, intc_ipr_address); - restore_flags(flags); -} - -static void mask_and_ack_onChip2(unsigned int irq) -{ - disable_onChip2_irq(irq); - if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) { - /* Clear external interrupt request */ - int a = ctrl_inb(INTC_IRR0); - a &= ~(1 << (irq - IRQ0_IRQ)); - ctrl_outb(a, INTC_IRR0); - } -} - -static void end_onChip2_irq(unsigned int irq) -{ - enable_onChip2_irq(irq); -} -#endif /* CONFIG_CPU_SUBTYPE_SH7709 */ - -void __init init_IRQ(void) -{ - int i; - - for (i = TIMER_IRQ; i < NR_IRQS; i++) { - irq_desc[i].handler = &onChip_irq_type; - } - -#ifdef CONFIG_CPU_SUBTYPE_SH7709 - - /* - * Initialize the Interrupt Controller (INTC) - * registers to their power on values - */ - - ctrl_outb(0, INTC_IRR0); - ctrl_outb(0, INTC_IRR1); - ctrl_outb(0, INTC_IRR2); - - ctrl_outw(0, INTC_ICR0); - ctrl_outw(0, INTC_ICR1); - ctrl_outw(0, INTC_ICR2); - ctrl_outw(0, INTC_INTER); - ctrl_outw(0, INTC_IPRA); - ctrl_outw(0, INTC_IPRB); - ctrl_outw(0, INTC_IPRC); - ctrl_outw(0, INTC_IPRD); - ctrl_outw(0, INTC_IPRE); - - for (i = IRQ0_IRQ; i < NR_IRQS; i++) { - irq_desc[i].handler = &onChip2_irq_type; - } - - /* - * Enable external irq(INTC IRQ mode). - * You should set corresponding bits of PFC to "00" - * to enable these interrupts. - */ - set_ipr_data(IRQ0_IRQ, IRQ0_IRP_OFFSET, IRQ0_PRIORITY); - set_ipr_data(IRQ1_IRQ, IRQ1_IRP_OFFSET, IRQ1_PRIORITY); - set_ipr_data(IRQ2_IRQ, IRQ2_IRP_OFFSET, IRQ2_PRIORITY); - set_ipr_data(IRQ3_IRQ, IRQ3_IRP_OFFSET, IRQ3_PRIORITY); - set_ipr_data(IRQ4_IRQ, IRQ4_IRP_OFFSET, IRQ4_PRIORITY); - set_ipr_data(IRQ5_IRQ, IRQ5_IRP_OFFSET, IRQ5_PRIORITY); -#endif /* CONFIG_CPU_SUBTYPE_SH7709 */ -} diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/ptrace.c linux/arch/sh/kernel/ptrace.c --- v2.3.99-pre8/linux/arch/sh/kernel/ptrace.c Tue Apr 11 15:09:14 2000 +++ linux/arch/sh/kernel/ptrace.c Sat May 20 12:05:29 2000 @@ -1,4 +1,4 @@ -/* $Id: ptrace.c,v 1.4 2000/03/22 13:59:01 gniibe Exp $ +/* $Id: ptrace.c,v 1.5 2000/05/09 01:42:21 gniibe Exp $ * * linux/arch/sh/kernel/ptrace.c * @@ -137,7 +137,6 @@ { struct task_struct *child, *tsk = current; struct user * dummy = NULL; - unsigned long flags; int ret; lock_kernel(); @@ -154,15 +153,19 @@ ret = -ESRCH; read_lock(&tasklist_lock); child = find_task_by_pid(pid); - read_unlock(&tasklist_lock); /* FIXME!!! */ + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); if (!child) goto out; + ret = -EPERM; if (pid == 1) /* you may not mess with init */ - goto out; + goto out_tsk; + if (request == PTRACE_ATTACH) { if (child == tsk) - goto out; + goto out_tsk; if ((!child->dumpable || (tsk->uid != child->euid) || (tsk->uid != child->suid) || @@ -171,34 +174,33 @@ (tsk->gid != child->sgid) || (!cap_issubset(child->cap_permitted, tsk->cap_permitted)) || (tsk->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) - goto out; + goto out_tsk; /* the same process cannot be attached many times */ if (child->flags & PF_PTRACED) - goto out; + goto out_tsk; child->flags |= PF_PTRACED; - write_lock_irqsave(&tasklist_lock, flags); + write_lock_irq(&tasklist_lock); if (child->p_pptr != tsk) { REMOVE_LINKS(child); child->p_pptr = tsk; SET_LINKS(child); } - write_unlock_irqrestore(&tasklist_lock, flags); + write_unlock_irq(&tasklist_lock); send_sig(SIGSTOP, child, 1); ret = 0; - goto out; + goto out_tsk; } ret = -ESRCH; if (!(child->flags & PF_PTRACED)) - goto out; + goto out_tsk; if (child->state != TASK_STOPPED) { if (request != PTRACE_KILL) - goto out; + goto out_tsk; } if (child->p_pptr != tsk) - goto out; - + goto out_tsk; switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -357,11 +359,11 @@ break; child->flags &= ~(PF_PTRACED|PF_TRACESYS); child->exit_code = data; - write_lock_irqsave(&tasklist_lock, flags); + write_lock_irq(&tasklist_lock); REMOVE_LINKS(child); child->p_pptr = child->p_opptr; SET_LINKS(child); - write_unlock_irqrestore(&tasklist_lock, flags); + write_unlock_irq(&tasklist_lock); wake_up_process(child); ret = 0; break; @@ -371,6 +373,8 @@ ret = -EIO; break; } +out_tsk: + free_task_struct(child); out: unlock_kernel(); return ret; diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/setup_se.c linux/arch/sh/kernel/setup_se.c --- v2.3.99-pre8/linux/arch/sh/kernel/setup_se.c Wed Dec 31 16:00:00 1969 +++ linux/arch/sh/kernel/setup_se.c Sat May 20 12:05:29 2000 @@ -0,0 +1,123 @@ +/* $Id: setup_se.c,v 1.6 2000/05/14 08:41:25 gniibe Exp $ + * + * linux/arch/sh/kernel/setup_se.c + * + * Copyright (C) 2000 Kazumoto Kojima + * + * Hitachi SolutionEngine Support. + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * Configure the Super I/O chip + */ +static void __init smsc_config(int index, int data) +{ + outb_p(index, INDEX_PORT); + outb_p(data, DATA_PORT); +} + +static void __init init_smsc(void) +{ + outb_p(CONFIG_ENTER, CONFIG_PORT); + outb_p(CONFIG_ENTER, CONFIG_PORT); + + /* FDC */ + smsc_config(CURRENT_LDN_INDEX, LDN_FDC); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */ + + /* IDE1 */ + smsc_config(CURRENT_LDN_INDEX, LDN_IDE1); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */ + + /* AUXIO (GPIO): to use IDE1 */ + smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO); + smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */ + smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */ + + /* COM1 */ + smsc_config(CURRENT_LDN_INDEX, LDN_COM1); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IO_BASE_HI_INDEX, 0x03); + smsc_config(IO_BASE_LO_INDEX, 0xf8); + smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */ + + /* RTC */ + smsc_config(CURRENT_LDN_INDEX, LDN_RTC); + smsc_config(ACTIVATE_INDEX, 0x01); + smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */ + + /* XXX: COM2, PARPORT, KBD, and MOUSE will come here... */ + outb_p(CONFIG_EXIT, CONFIG_PORT); +} + +/* + * Initialize IRQ setting + */ +static void __init init_se_IRQ(void) +{ + int i; + + /* + * Super I/O (Just mimic PC): + * 1: keyboard + * 3: serial 0 + * 4: serial 1 + * 5: printer + * 6: floppy + * 8: rtc + * 12: mouse + * 14: ide0 + */ + set_ipr_data(14, BCR_ILCRA, 2, 0x0f-14); + set_ipr_data(12, BCR_ILCRA, 1, 0x0f-12); + set_ipr_data( 8, BCR_ILCRB, 1, 0x0f- 8); + set_ipr_data( 6, BCR_ILCRC, 3, 0x0f- 6); + set_ipr_data( 5, BCR_ILCRC, 2, 0x0f- 5); + set_ipr_data( 4, BCR_ILCRC, 1, 0x0f- 4); + set_ipr_data( 3, BCR_ILCRC, 0, 0x0f- 3); + set_ipr_data( 1, BCR_ILCRD, 3, 0x0f- 1); + + set_ipr_data(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */ + + set_ipr_data( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */ + set_ipr_data(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */ + set_ipr_data( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */ + set_ipr_data( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */ + + /* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */ + /* NOTE: #2 and #13 are not used on PC */ + set_ipr_data(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */ + set_ipr_data( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */ + + for (i = 0; i < 15; i++) { + make_ipr_irq(i); + } +} + +/* + * Initialize the board + */ +int __init setup_se(void) +{ + init_se_IRQ(); + init_smsc(); + /* XXX: RTC setting comes here */ + + printk(KERN_INFO "Hitach SolutionEngine Setup...done\n"); + return 0; +} + +module_init(setup_se); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/signal.c linux/arch/sh/kernel/signal.c --- v2.3.99-pre8/linux/arch/sh/kernel/signal.c Wed Apr 26 16:34:07 2000 +++ linux/arch/sh/kernel/signal.c Sat May 20 12:05:29 2000 @@ -165,11 +165,11 @@ unsigned long flags; if (!tsk->used_math) { - sc->sc_ownedfp = 0; + __copy_to_user(&sc->sc_ownedfp, 0, sizeof(int)); return 0; } - sc->sc_ownedfp = 1; + __copy_to_user(&sc->sc_ownedfp, 1, sizeof(int)); /* This will cause a "finit" to be triggered by the next attempted FPU operation by the 'current' process. diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/time.c linux/arch/sh/kernel/time.c --- v2.3.99-pre8/linux/arch/sh/kernel/time.c Wed Apr 26 16:34:07 2000 +++ linux/arch/sh/kernel/time.c Sat May 20 12:05:29 2000 @@ -47,9 +47,6 @@ #define RCR2_RESET 0x02 /* Reset bit */ #define RCR2_START 0x01 /* Start bit */ -#define RTC_IRQ 22 -#define RTC_IPR_OFFSET 0 - #if defined(__sh3__) #define TMU_TOCR 0xfffffe90 /* Byte access */ #define TMU_TSTR 0xfffffe92 /* Byte access */ @@ -204,13 +201,6 @@ static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { do_timer(regs); -#ifdef TAKESHI - { - unsigned long what_is_this=0xa4000124; - - ctrl_outb(ctrl_inb(what_is_this)+1,what_is_this); - } -#endif #if 0 if (!user_mode(regs)) sh_do_profile(regs->pc); @@ -393,23 +383,23 @@ void __init time_init(void) { - unsigned int cpu_clock, master_clock, module_clock; - unsigned short ifc, pfc; + unsigned int cpu_clock, master_clock, bus_clock, module_clock; + unsigned short frqcr, ifc, pfc; unsigned long interval; #if defined(__sh3__) static int ifc_table[] = { 1, 2, 4, 1, 3, 1, 1, 1 }; static int pfc_table[] = { 1, 2, 4, 1, 3, 6, 1, 1 }; + static int stc_table[] = { 1, 2, 3, 4, 6, 8, 1, 1 }; #elif defined(__SH4__) static int ifc_table[] = { 1, 2, 3, 4, 6, 8, 1, 1 }; +#define bfc_table ifc_table /* Same */ static int pfc_table[] = { 2, 3, 4, 6, 8, 2, 2, 2 }; #endif xtime.tv_sec = get_rtc_time(); xtime.tv_usec = 0; - set_ipr_data(TIMER_IRQ, TIMER_IPR_OFFSET, TIMER_PRIORITY); setup_irq(TIMER_IRQ, &irq0); - set_ipr_data(RTC_IRQ, RTC_IPR_OFFSET, TIMER_PRIORITY); setup_irq(RTC_IRQ, &irq1); /* Check how fast it is.. */ @@ -420,23 +410,37 @@ (cpu_clock / 1000000), (cpu_clock % 1000000)/10000); #if defined(__sh3__) { - unsigned short tmp; - tmp = (ctrl_inw(FRQCR) & 0x000c) >> 2; - tmp |= (ctrl_inw(FRQCR) & 0x4000) >> 12; - ifc = ifc_table[tmp & 0x0007]; - tmp = ctrl_inw(FRQCR) & 0x0003; - tmp |= (ctrl_inw(FRQCR) & 0x2000) >> 11; - pfc = pfc_table[ctrl_inw(FRQCR) & 0x0007]; + unsigned short tmp, stc; + frqcr = ctrl_inw(FRQCR); + tmp = (frqcr & 0x8000) >> 13; + tmp |= (frqcr & 0x0030) >> 4; + stc = stc_table[tmp]; + tmp = (frqcr & 0x4000) >> 12; + tmp |= (frqcr & 0x000c) >> 2; + ifc = ifc_table[tmp]; + tmp = (frqcr & 0x2000) >> 11; + tmp |= frqcr & 0x0003; + pfc = pfc_table[tmp]; + master_clock = cpu_clock; + bus_clock = master_clock/pfc; } #elif defined(__SH4__) - ifc = ifc_table[(ctrl_inw(FRQCR)>> 6) & 0x0007]; - pfc = pfc_table[ctrl_inw(FRQCR) & 0x0007]; + { + unsigned short bfc; + frqcr = ctrl_inw(FRQCR); + ifc = ifc_table[(frqcr>> 6) & 0x0007]; + bfc = bfc_table[(frqcr>> 3) & 0x0007]; + pfc = pfc_table[frqcr & 0x0007]; + master_clock = cpu_clock * ifc; + bus_clock = master_clock/bfc; + } #endif - master_clock = cpu_clock * ifc; + printk("Bus clock: %d.%02dMHz\n", + (bus_clock/1000000), (bus_clock % 1000000)/10000); module_clock = master_clock/pfc; printk("Module clock: %d.%02dMHz\n", (module_clock/1000000), (module_clock % 1000000)/10000); - interval = (module_clock/400); + interval = (module_clock/(HZ*4)); printk("Interval = %ld\n", interval); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/lib/checksum.S linux/arch/sh/lib/checksum.S --- v2.3.99-pre8/linux/arch/sh/lib/checksum.S Sun Nov 7 16:37:34 1999 +++ linux/arch/sh/lib/checksum.S Sat May 20 12:05:29 2000 @@ -1,4 +1,4 @@ -/* $Id: checksum.S,v 1.2 1999/10/29 13:06:55 gniibe Exp $ +/* $Id: checksum.S,v 1.4 2000/05/14 08:41:26 gniibe Exp $ * * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket @@ -49,95 +49,99 @@ * Fortunately, it is easy to convert 2-byte alignment to 4-byte * alignment for the unrolled loop. */ - mov r5,r1 - mov r4,r0 - tst #2,r0 ! Check alignment. + mov $r5, $r1 + mov $r4, $r0 + tst #2, $r0 ! Check alignment. bt 2f ! Jump if alignment is ok. ! - add #-2,r5 ! Alignment uses up two bytes. - cmp/pz r5 ! + add #-2, $r5 ! Alignment uses up two bytes. + cmp/pz $r5 ! bt/s 1f ! Jump if we had at least two bytes. clrt bra 6f - add #2,r5 ! r5 was < 2. Deal with it. + add #2, $r5 ! $r5 was < 2. Deal with it. 1: - mov.w @r4+,r0 - extu.w r0,r0 - addc r0,r6 + mov.w @$r4+, $r0 + extu.w $r0, $r0 + addc $r0, $r6 bf 2f - add #1,r6 + add #1, $r6 2: - mov #-5,r0 - shld r0,r5 - tst r5,r5 + mov #-5, $r0 + shld $r0, $r5 + tst $r5, $r5 bt/s 4f ! if it's =0, go to 4f clrt + .align 2 3: - mov.l @r4+,r0 - addc r0,r6 - mov.l @r4+,r0 - addc r0,r6 - mov.l @r4+,r0 - addc r0,r6 - mov.l @r4+,r0 - addc r0,r6 - mov.l @r4+,r0 - addc r0,r6 - mov.l @r4+,r0 - addc r0,r6 - mov.l @r4+,r0 - addc r0,r6 - mov.l @r4+,r0 - addc r0,r6 - movt r0 - dt r5 + mov.l @$r4+, $r0 + mov.l @$r4+, $r2 + mov.l @$r4+, $r3 + addc $r0, $r6 + mov.l @$r4+, $r0 + addc $r2, $r6 + mov.l @$r4+, $r2 + addc $r3, $r6 + mov.l @$r4+, $r3 + addc $r0, $r6 + mov.l @$r4+, $r0 + addc $r2, $r6 + mov.l @$r4+, $r2 + addc $r3, $r6 + addc $r0, $r6 + addc $r2, $r6 + movt $r0 + dt $r5 bf/s 3b - cmp/eq #1,r0 - mov #0,r0 - addc r0,r6 + cmp/eq #1, $r0 + ! here, we know $r5==0 + addc $r5, $r6 ! add carry to $r6 4: - mov r1,r5 - mov #0x1c,r0 - and r0,r5 - tst r5,r5 + mov $r1, $r0 + and #0x1c, $r0 + tst $r0, $r0 bt/s 6f - clrt - shlr2 r5 + mov $r0, $r5 + shlr2 $r5 + mov #0, $r2 5: - mov.l @r4+,r0 - addc r0,r6 - movt r0 - dt r5 + addc $r2, $r6 + mov.l @$r4+, $r2 + movt $r0 + dt $r5 bf/s 5b - cmp/eq #1,r0 - mov #0,r0 - addc r0,r6 + cmp/eq #1, $r0 + addc $r2, $r6 + addc $r5, $r6 ! $r5==0 here, so it means add carry-bit 6: - mov r1,r5 - mov #3,r0 - and r0,r5 - tst r5,r5 + mov $r1, $r5 + mov #3, $r0 + and $r0, $r5 + tst $r5, $r5 bt 9f ! if it's =0 go to 9f - mov #2,r1 - cmp/hs r1,r5 + mov #2, $r1 + cmp/hs $r1, $r5 bf 7f - mov.w @r4+,r0 - extu.w r0,r0 - cmp/eq r1,r5 + mov.w @r4+, $r0 + extu.w $r0, $r0 + cmp/eq $r1, $r5 bt/s 8f clrt - shll16 r0 - addc r0,r6 + shll16 $r0 + addc $r0, $r6 7: - mov.b @r4+,r0 - extu.b r0,r0 + mov.b @$r4+, $r0 + extu.b $r0, $r0 +#ifndef __LITTLE_ENDIAN__ + shll8 $r0 +#endif 8: - addc r0,r6 - mov #0,r0 - addc r0,r6 + addc $r0, $r6 + mov #0, $r0 + addc $r0, $r6 9: rts - mov r6,r0 + mov $r6, $r0 /* unsigned int csum_partial_copy_generic (const char *src, char *dst, int len, @@ -167,6 +171,16 @@ .long 9999b, 6002f ; \ .previous +! +! r4: const char *SRC +! r5: char *DST +! r6: int LEN +! r7: int SUM +! +! on stack: +! int *SRC_ERR_PTR +! int *DST_ERR_PTR +! ENTRY(csum_partial_copy_generic) mov.l r5,@-r15 mov.l r6,@-r15 @@ -179,7 +193,7 @@ bt/s 1f clrt bra 4f - add #2,r6 ! ecx was < 2. Deal with it. + add #2,r6 ! $r6 was < 2. Deal with it. SRC(1: mov.w @r4+,r0 ) DST( mov.w r0,@r5 ) add #2,r5 @@ -273,6 +287,9 @@ SRC(5: mov.b @r4+,r0 ) DST( mov.b r0,@r5 ) extu.b r0,r0 +#ifndef __LITTLE_ENDIAN__ + shll8 r0 +#endif 6: addc r0,r7 mov #0,r0 addc r0,r7 @@ -299,7 +316,7 @@ mov.l 8000f,r0 jmp @r0 nop - .balign 4 + .align 2 8000: .long 5000b 6002: @@ -309,7 +326,7 @@ mov.l 8001f,r0 jmp @r0 nop - .balign 4 + .align 2 8001: .long 5000b .previous diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/mm/cache.c linux/arch/sh/mm/cache.c --- v2.3.99-pre8/linux/arch/sh/mm/cache.c Wed Apr 26 16:34:07 2000 +++ linux/arch/sh/mm/cache.c Sat May 20 12:05:29 2000 @@ -49,7 +49,7 @@ #elif defined(__SH4__) #define CCR 0xff00001c /* Address of Cache Control Register */ #define CCR_CACHE_VAL 0x00000105 /* 8k+16k-byte cache,P1-wb,enable */ -#define CCR_CACHE_INIT 0x0000090d /* 8k+16k-byte cache,CF,P1-wb,enable */ +#define CCR_CACHE_INIT 0x0000090d /* ICI,ICE(8k), OCI,P1-wb,OCE(16k) */ #define CCR_CACHE_ENABLE 0x00000101 #define CACHE_IC_ADDRESS_ARRAY 0xf0000000 @@ -60,143 +60,41 @@ #define CACHE_OC_WAY_SHIFT 13 #define CACHE_IC_WAY_SHIFT 13 #define CACHE_OC_ENTRY_SHIFT 5 +#define CACHE_IC_ENTRY_SHIFT 5 #define CACHE_OC_ENTRY_MASK 0x3fe0 +#define CACHE_OC_ENTRY_PHYS_MASK 0x0fe0 #define CACHE_IC_ENTRY_MASK 0x1fe0 +#define CACHE_IC_NUM_ENTRIES 256 #define CACHE_OC_NUM_ENTRIES 512 #define CACHE_OC_NUM_WAYS 1 #define CACHE_IC_NUM_WAYS 1 #endif -/* Write back caches to memory (if needed) and invalidates the caches */ -void cache_flush_area(unsigned long start, unsigned long end) -{ - unsigned long flags; - unsigned long addr, data, v, p; - - start &= ~(L1_CACHE_BYTES-1); - save_and_cli(flags); - jump_to_P2(); - - for (v = start; v < end; v+=L1_CACHE_BYTES) { - p = __pa(v); - addr = CACHE_IC_ADDRESS_ARRAY | - (v&CACHE_IC_ENTRY_MASK) | 0x8 /* A-bit */; - data = (v&0xfffffc00); /* U=0, V=0 */ - ctrl_outl(data,addr); -#if CACHE_IC_ADDRESS_ARRAY != CACHE_OC_ADDRESS_ARRAY - asm volatile("ocbp %0" - : /* no output */ - : "m" (__m(v))); -#endif - } - back_to_P1(); - restore_flags(flags); -} - -/* Purge (just invalidate, no write back) the caches */ -/* This is expected to work well.. but.. - - On SH7708S, the write-back cache is written back on "purge". - (it's not expected, though). - - It seems that we have no way to just purge (with no write back action) - the cache line. */ -void cache_purge_area(unsigned long start, unsigned long end) -{ - unsigned long flags; - unsigned long addr, data, v, p, j; - - start &= ~(L1_CACHE_BYTES-1); - save_and_cli(flags); - jump_to_P2(); - - for (v = start; v < end; v+=L1_CACHE_BYTES) { - p = __pa(v); - for (j=0; jvm_mm, addr, addr+PAGE_SIZE); } -void __flush_page_to_ram(unsigned long page) -{ /* Page is in physical address */ - /* XXX: for the time being... */ - flush_cache_all(); +/* + * After accessing the memory from kernel space (P1-area), we need to + * write back the cache line, to avoid "alias" issues. + * + * We search the D-cache to see if we have the entries corresponding to + * the page, and if found, write back them. + */ +void flush_page_to_ram(struct page *pg) +{ + unsigned long phys, addr, data, i; + + /* Physical address of this page */ + phys = (pg - mem_map)*PAGE_SIZE + __MEMORY_START; + + jump_to_P2(); + /* Loop all the D-cache */ + for (i=0; i extern void die(const char *,struct pt_regs *,long); +static void __flush_tlb_page(struct mm_struct *mm, unsigned long page); /* * Ugly, ugly, but the goto's result in better assembly.. @@ -167,12 +168,17 @@ * make sure we exit gracefully rather than endlessly redo * the fault. */ - { - int fault = handle_mm_fault(mm, vma, address, writeaccess); - if (fault < 0) - goto out_of_memory; - if (!fault) - goto do_sigbus; + switch (handle_mm_fault(mm, vma, address, writeaccess)) { + case 1: + tsk->min_flt++; + break; + case 2: + tsk->maj_flt++; + break; + case 0: + goto do_sigbus; + default: + goto out_of_memory; } up(&mm->mmap_sem); @@ -209,18 +215,20 @@ printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); else printk(KERN_ALERT "Unable to handle kernel paging request"); - printk(" at virtual address %08lx\n",address); + printk(" at virtual address %08lx\n", address); printk(KERN_ALERT "pc = %08lx\n", regs->pc); - asm volatile("mov.l %1,%0" + asm volatile("mov.l %1, %0" : "=r" (page) : "m" (__m(MMU_TTB))); - page = ((unsigned long *) page)[address >> 22]; - printk(KERN_ALERT "*pde = %08lx\n", page); - if (page & _PAGE_PRESENT) { - page &= PAGE_MASK; - address &= 0x003ff000; - page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT]; - printk(KERN_ALERT "*pte = %08lx\n", page); + if (page) { + page = ((unsigned long *) page)[address >> 22]; + printk(KERN_ALERT "*pde = %08lx\n", page); + if (page & _PAGE_PRESENT) { + page &= PAGE_MASK; + address &= 0x003ff000; + page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT]; + printk(KERN_ALERT "*pte = %08lx\n", page); + } } die("Oops", regs, writeaccess); do_exit(SIGKILL); @@ -261,18 +269,24 @@ unsigned long pteaddr; save_and_cli(flags); +#if defined(__SH4__) /* - * We don't need to set PTEH register. - * It's automatically set by the hardware. + * ITLB is not affected by "ldtlb" instruction. + * So, we need to flush the entry by ourselves. */ + __flush_tlb_page(vma->vm_mm, address&PAGE_MASK); +#endif + + /* Set PTEH register */ + pteaddr = (address & MMU_VPN_MASK) | + (vma->vm_mm->context & MMU_CONTEXT_ASID_MASK); + ctrl_outl(pteaddr, MMU_PTEH); + + /* Set PTEL register */ pteval = pte_val(pte); pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ pteval |= _PAGE_FLAGS_HARDWARE_DEFAULT; /* add default flags */ - /* Set PTEL register */ ctrl_outl(pteval, MMU_PTEL); - /* Set PTEH register */ - pteaddr = (address & MMU_VPN_MASK) | (vma->vm_mm->context & MMU_CONTEXT_ASID_MASK); - ctrl_outl(pteaddr, MMU_PTEH); /* Load the TLB */ asm volatile("ldtlb": /* no output */ : /* no input */ : "memory"); @@ -306,20 +320,6 @@ addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT; data = page | asid; /* VALID bit is off */ ctrl_outl(data, addr); -#if 0 /* Not need when using ASSOC. ??? */ - { - int i; - for (i=0; i<4; i++) { - addr = MMU_ITLB_ADDRESS_ARRAY | (i<<8); - data = ctrl_inl(addr); - data &= ~0x300; - if (data == (page | asid)) { - ctrl_outl(data, addr); - break; - } - } - } -#endif back_to_P1(); #endif if (saved_asid != MMU_NO_ASID) @@ -383,9 +383,16 @@ { unsigned long flags, status; + /* + * Flush all the TLB. + * + * Write to the MMU control register's bit: + * TF-bit for SH-3, TI-bit for SH-4. + * It's same position, bit #2. + */ save_and_cli(flags); status = ctrl_inl(MMUCR); - status |= 0x04; /* Set TF-bit to flush */ - ctrl_outl(status,MMUCR); + status |= 0x04; + ctrl_outl(status, MMUCR); restore_flags(flags); } diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/config.in linux/arch/sparc/config.in --- v2.3.99-pre8/linux/arch/sparc/config.in Tue Apr 11 15:09:14 2000 +++ linux/arch/sparc/config.in Mon May 22 09:50:53 2000 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.92 2000/03/29 11:56:48 davem Exp $ +# $Id: config.in,v 1.93 2000/05/22 08:12:19 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -186,6 +186,11 @@ if [ "$CONFIG_NETDEVICES" = "y" ]; then tristate ' Dummy net driver support' CONFIG_DUMMY tristate ' Bonding driver support' CONFIG_BONDING + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + if [ "$CONFIG_NETLINK" = "y" ]; then + tristate ' Ethertap network tap (EXPERIMENTAL)' CONFIG_ETHERTAP + fi + fi tristate ' PPP (point-to-point) support' CONFIG_PPP if [ ! "$CONFIG_PPP" = "n" ]; then dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile --- v2.3.99-pre8/linux/arch/sparc/kernel/Makefile Fri May 12 14:18:55 2000 +++ linux/arch/sparc/kernel/Makefile Mon May 22 09:50:53 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.53 2000/03/31 04:06:19 davem Exp $ +# $Id: Makefile,v 1.54 2000/05/12 23:51:24 davem Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also @@ -59,13 +59,11 @@ @echo "#ifndef CONFIG_SMP" >> asm_offsets.h @echo "" >> asm_offsets.h @echo "#include " > tmp.c - @echo "#undef __SMP__" >> tmp.c @echo "#undef CONFIG_SMP" >> tmp.c @echo "#include " >> tmp.c $(CPP) $(CPPFLAGS) tmp.c -o tmp.i @echo "/* Automatically generated. Do not edit. */" > check_asm.c @echo "#include " >> check_asm.c - @echo "#undef __SMP__" >> check_asm.c @echo "#undef CONFIG_SMP" >> check_asm.c @echo "#include " >> check_asm.c @echo 'struct task_struct _task;' >> check_asm.c diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S --- v2.3.99-pre8/linux/arch/sparc/kernel/entry.S Thu May 11 15:30:06 2000 +++ linux/arch/sparc/kernel/entry.S Mon May 22 09:50:53 2000 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.163 1999/11/19 04:11:24 davem Exp $ +/* $Id: entry.S,v 1.164 2000/05/09 17:40:13 davem Exp $ * arch/sparc/kernel/entry.S: Sparc trap low-level entry points. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S --- v2.3.99-pre8/linux/arch/sparc/kernel/head.S Thu May 11 15:30:06 2000 +++ linux/arch/sparc/kernel/head.S Mon May 22 09:50:53 2000 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.102 2000/01/29 01:08:54 anton Exp $ +/* $Id: head.S,v 1.103 2000/05/09 17:40:13 davem Exp $ * head.S: The initial boot code for the Sparc port of Linux. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c --- v2.3.99-pre8/linux/arch/sparc/kernel/irq.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc/kernel/irq.c Mon May 22 09:50:53 2000 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.102 2000/02/25 05:44:35 davem Exp $ +/* $Id: irq.c,v 1.103 2000/05/09 17:40:13 davem Exp $ * arch/sparc/kernel/irq.c: Interrupt request handling routines. On the * Sparc the IRQ's are basically 'cast in stone' * and you are supposed to probe the prom's device diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c --- v2.3.99-pre8/linux/arch/sparc/kernel/process.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc/kernel/process.c Mon May 22 09:50:53 2000 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.146 2000/03/01 02:53:27 davem Exp $ +/* $Id: process.c,v 1.147 2000/05/09 17:40:13 davem Exp $ * linux/arch/sparc/kernel/process.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c --- v2.3.99-pre8/linux/arch/sparc/kernel/setup.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc/kernel/setup.c Mon May 22 09:50:53 2000 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.117 2000/03/27 12:14:54 davem Exp $ +/* $Id: setup.c,v 1.118 2000/05/09 17:40:13 davem Exp $ * linux/arch/sparc/kernel/setup.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c --- v2.3.99-pre8/linux/arch/sparc/kernel/signal.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc/kernel/signal.c Mon May 22 09:50:53 2000 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.102 2000/04/08 02:11:36 davem Exp $ +/* $Id: signal.c,v 1.103 2000/05/09 17:40:13 davem Exp $ * linux/arch/sparc/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c --- v2.3.99-pre8/linux/arch/sparc/kernel/sparc_ksyms.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc/kernel/sparc_ksyms.c Mon May 22 09:50:53 2000 @@ -1,4 +1,4 @@ -/* $Id: sparc_ksyms.c,v 1.96 2000/03/16 09:12:49 jj Exp $ +/* $Id: sparc_ksyms.c,v 1.97 2000/05/09 17:40:13 davem Exp $ * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/sun4d_irq.c linux/arch/sparc/kernel/sun4d_irq.c --- v2.3.99-pre8/linux/arch/sparc/kernel/sun4d_irq.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc/kernel/sun4d_irq.c Mon May 22 09:50:53 2000 @@ -1,4 +1,4 @@ -/* $Id: sun4d_irq.c,v 1.24 1999/12/27 06:08:34 anton Exp $ +/* $Id: sun4d_irq.c,v 1.25 2000/05/09 17:40:13 davem Exp $ * arch/sparc/kernel/sun4d_irq.c: * SS1000/SC2000 interrupt handling. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c --- v2.3.99-pre8/linux/arch/sparc/kernel/sys_sunos.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc/kernel/sys_sunos.c Mon May 22 09:50:53 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos.c,v 1.122 2000/04/27 02:49:03 davem Exp $ +/* $Id: sys_sunos.c,v 1.123 2000/05/22 07:29:39 davem Exp $ * sys_sunos.c: SunOS specific syscall compatibility support. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -634,7 +634,6 @@ extern dev_t get_unnamed_dev(void); extern void put_unnamed_dev(dev_t); -extern asmlinkage long do_sys_mount(char *, char *, char *, int, void *); extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen); extern asmlinkage int sys_socket(int family, int type, int protocol); extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); @@ -754,7 +753,7 @@ linux_nfs_mount.hostname [255] = 0; putname (the_name); - return do_sys_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount); + return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount); } asmlinkage int @@ -814,7 +813,7 @@ ret = PTR_ERR(dev_fname); if (IS_ERR(dev_fname)) goto out2; - ret = do_sys_mount(dev_fname, dir_page, type_page, linux_flags, NULL); + ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL); if (dev_fname) putname(dev_fname); out2: diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/time.c linux/arch/sparc/kernel/time.c --- v2.3.99-pre8/linux/arch/sparc/kernel/time.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc/kernel/time.c Mon May 22 09:50:53 2000 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.54 2000/04/13 08:14:30 anton Exp $ +/* $Id: time.c,v 1.55 2000/05/09 17:40:13 davem Exp $ * linux/arch/sparc/kernel/time.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/traps.c linux/arch/sparc/kernel/traps.c --- v2.3.99-pre8/linux/arch/sparc/kernel/traps.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc/kernel/traps.c Mon May 22 09:50:53 2000 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.61 2000/01/21 11:38:41 jj Exp $ +/* $Id: traps.c,v 1.62 2000/05/09 17:40:13 davem Exp $ * arch/sparc/kernel/traps.c * * Copyright 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/lib/rwsem.S linux/arch/sparc/lib/rwsem.S --- v2.3.99-pre8/linux/arch/sparc/lib/rwsem.S Thu May 11 15:30:06 2000 +++ linux/arch/sparc/lib/rwsem.S Mon May 22 09:50:53 2000 @@ -1,4 +1,4 @@ -/* $Id: rwsem.S,v 1.4 2000/02/13 07:59:39 anton Exp $ +/* $Id: rwsem.S,v 1.5 2000/05/09 17:40:13 davem Exp $ * Assembly part of rw semaphores. * * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/btfixup.c linux/arch/sparc/mm/btfixup.c --- v2.3.99-pre8/linux/arch/sparc/mm/btfixup.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc/mm/btfixup.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: btfixup.c,v 1.9 1999/12/27 06:30:02 anton Exp $ +/* $Id: btfixup.c,v 1.10 2000/05/09 17:40:13 davem Exp $ * btfixup.c: Boot time code fixup and relocator, so that * we can get rid of most indirect calls to achieve single * image sun4c and srmmu kernel. diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/hypersparc.S linux/arch/sparc/mm/hypersparc.S --- v2.3.99-pre8/linux/arch/sparc/mm/hypersparc.S Thu May 11 15:30:06 2000 +++ linux/arch/sparc/mm/hypersparc.S Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: hypersparc.S,v 1.14 1999/08/14 03:51:47 anton Exp $ +/* $Id: hypersparc.S,v 1.15 2000/05/09 17:40:13 davem Exp $ * hypersparc.S: High speed Hypersparc mmu/cache operations. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c --- v2.3.99-pre8/linux/arch/sparc/mm/init.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc/mm/init.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.84 2000/03/15 23:26:26 anton Exp $ +/* $Id: init.c,v 1.85 2000/05/09 17:40:13 davem Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c --- v2.3.99-pre8/linux/arch/sparc/mm/srmmu.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc/mm/srmmu.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.208 2000/02/14 04:52:33 jj Exp $ +/* $Id: srmmu.c,v 1.209 2000/05/09 17:40:13 davem Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c --- v2.3.99-pre8/linux/arch/sparc/mm/sun4c.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc/mm/sun4c.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.191 2000/04/08 02:11:41 davem Exp $ +/* $Id: sun4c.c,v 1.192 2000/05/09 17:40:13 davem Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/swift.S linux/arch/sparc/mm/swift.S --- v2.3.99-pre8/linux/arch/sparc/mm/swift.S Thu May 11 15:30:06 2000 +++ linux/arch/sparc/mm/swift.S Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: swift.S,v 1.4 2000/02/12 03:08:47 zaitcev Exp $ +/* $Id: swift.S,v 1.5 2000/05/09 17:40:13 davem Exp $ * swift.S: MicroSparc-II mmu/cache operations. * * Copyright (C) 1999 David S. Miller (davem@redhat.com) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/tsunami.S linux/arch/sparc/mm/tsunami.S --- v2.3.99-pre8/linux/arch/sparc/mm/tsunami.S Thu May 11 15:30:06 2000 +++ linux/arch/sparc/mm/tsunami.S Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: tsunami.S,v 1.3 1999/10/09 05:32:19 zaitcev Exp $ +/* $Id: tsunami.S,v 1.4 2000/05/09 17:40:13 davem Exp $ * tsunami.S: High speed MicroSparc-I mmu/cache operations. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/viking.S linux/arch/sparc/mm/viking.S --- v2.3.99-pre8/linux/arch/sparc/mm/viking.S Thu May 11 15:30:06 2000 +++ linux/arch/sparc/mm/viking.S Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: viking.S,v 1.15 2000/01/15 00:51:36 anton Exp $ +/* $Id: viking.S,v 1.16 2000/05/09 17:40:13 davem Exp $ * viking.S: High speed Viking cache/mmu operations * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.3.99-pre8/linux/arch/sparc64/config.in Fri May 12 14:18:55 2000 +++ linux/arch/sparc64/config.in Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.109 2000/05/02 06:35:59 davem Exp $ +# $Id: config.in,v 1.112 2000/05/22 08:12:19 davem Exp $ # For a description of the syntax of this configuration file, # see the Configure script. # @@ -204,6 +204,11 @@ if [ "$CONFIG_NETDEVICES" = "y" ]; then tristate ' Dummy net driver support' CONFIG_DUMMY tristate ' Bonding driver support' CONFIG_BONDING + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + if [ "$CONFIG_NETLINK" = "y" ]; then + tristate ' Ethertap network tap (EXPERIMENTAL)' CONFIG_ETHERTAP + fi + fi tristate ' PPP (point-to-point) support' CONFIG_PPP if [ ! "$CONFIG_PPP" = "n" ]; then dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile --- v2.3.99-pre8/linux/arch/sparc64/kernel/Makefile Fri May 12 14:18:55 2000 +++ linux/arch/sparc64/kernel/Makefile Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.53 2000/03/31 04:06:22 davem Exp $ +# $Id: Makefile,v 1.54 2000/05/12 23:51:24 davem Exp $ # Makefile for the linux kernel. # # Note! Dependencies are done automagically by 'make dep', which also diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/head.S linux/arch/sparc64/kernel/head.S --- v2.3.99-pre8/linux/arch/sparc64/kernel/head.S Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/kernel/head.S Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.64 2000/03/06 22:33:42 davem Exp $ +/* $Id: head.S,v 1.65 2000/05/09 17:40:13 davem Exp $ * head.S: Initial boot code for the Sparc64 port of Linux. * * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- v2.3.99-pre8/linux/arch/sparc64/kernel/ioctl32.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/kernel/ioctl32.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.89 2000/05/06 10:38:42 davem Exp $ +/* $Id: ioctl32.c,v 1.90 2000/05/22 07:29:39 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -2400,39 +2400,6 @@ return err; } -typedef struct blkelv_ioctl32_arg_s { - u32 queue_ID; - int read_latency; - int write_latency; - int max_bomb_segments; -} blkelv_ioctl32_arg_t; - -static int do_blkelv_ioctl(unsigned int fd, unsigned int cmd, blkelv_ioctl32_arg_t *arg) -{ - blkelv_ioctl_arg_t b; - int err; - mm_segment_t old_fs = get_fs(); - - if (cmd == BLKELVSET) { - err = get_user((long)b.queue_ID, &arg->queue_ID); - err |= __get_user(b.read_latency, &arg->read_latency); - err |= __get_user(b.write_latency, &arg->write_latency); - err |= __get_user(b.max_bomb_segments, &arg->max_bomb_segments); - if (err) return err; - } - set_fs (KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&b); - set_fs (old_fs); - if (cmd == BLKELVGET && !err) { - err = put_user((long)b.queue_ID, &arg->queue_ID); - err |= __put_user(b.read_latency, &arg->read_latency); - err |= __put_user(b.write_latency, &arg->write_latency); - err |= __put_user(b.max_bomb_segments, &arg->max_bomb_segments); - if (err) return err; - } - return err; -} - static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) { return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); @@ -2994,6 +2961,9 @@ COMPATIBLE_IOCTL(LV_SET_STATUS) COMPATIBLE_IOCTL(LV_SET_ALLOCATION) #endif /* LVM */ +/* elevator */ +COMPATIBLE_IOCTL(BLKELVGET) +COMPATIBLE_IOCTL(BLKELVSET) /* And these ioctls need translation */ HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32) HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf) @@ -3040,8 +3010,6 @@ HANDLE_IOCTL(BLKFRAGET, w_long) HANDLE_IOCTL(BLKSECTGET, w_long) HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) -HANDLE_IOCTL(BLKELVGET, do_blkelv_ioctl) -HANDLE_IOCTL(BLKELVSET, do_blkelv_ioctl) HANDLE_IOCTL(FBIOPUTCMAP32, fbiogetputcmap) HANDLE_IOCTL(FBIOGETCMAP32, fbiogetputcmap) HANDLE_IOCTL(FBIOSCURSOR32, fbiogscursor) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c --- v2.3.99-pre8/linux/arch/sparc64/kernel/irq.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/kernel/irq.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.86 2000/04/15 06:02:50 davem Exp $ +/* $Id: irq.c,v 1.87 2000/05/09 17:40:13 davem Exp $ * irq.c: UltraSparc IRQ handling/init/registry. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- v2.3.99-pre8/linux/arch/sparc64/kernel/process.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/kernel/process.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.106 2000/04/15 06:02:50 davem Exp $ +/* $Id: process.c,v 1.107 2000/05/09 17:40:14 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c --- v2.3.99-pre8/linux/arch/sparc64/kernel/setup.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/kernel/setup.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.53 2000/03/15 14:42:52 jj Exp $ +/* $Id: setup.c,v 1.54 2000/05/09 17:40:14 davem Exp $ * linux/arch/sparc64/kernel/setup.c * * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.3.99-pre8/linux/arch/sparc64/kernel/sparc64_ksyms.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.83 2000/04/19 08:38:25 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.84 2000/05/09 17:40:14 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.3.99-pre8/linux/arch/sparc64/kernel/sys_sparc32.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/kernel/sys_sparc32.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.146 2000/05/09 04:48:34 davem Exp $ +/* $Id: sys_sparc32.c,v 1.147 2000/05/22 07:29:40 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -1742,9 +1742,6 @@ return 0; } -extern long do_sys_mount(char * dev_page, char * dir_page, char * type_page, - unsigned long new_flags, char * data_page); - #define SMBFS_NAME "smbfs" #define NCPFS_NAME "ncpfs" @@ -1784,7 +1781,7 @@ goto dev_out; if (!is_smb && !is_ncp) { - err = do_sys_mount((char*)dev_page, (char*)dir_page, + err = do_mount((char*)dev_page, (char*)dir_page, (char*)type_page, new_flags, (char*)data_page); } else { if (is_ncp) @@ -1792,7 +1789,7 @@ else do_smb_super_data_conv((void *)data_page); - err = do_sys_mount((char*)dev_page, (char*)dir_page, + err = do_mount((char*)dev_page, (char*)dir_page, (char*)type_page, new_flags, (char*)data_page); } free_page(dir_page); diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c --- v2.3.99-pre8/linux/arch/sparc64/kernel/sys_sunos32.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/kernel/sys_sunos32.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.46 2000/04/27 02:49:03 davem Exp $ +/* $Id: sys_sunos32.c,v 1.47 2000/05/22 07:29:40 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) @@ -598,7 +598,6 @@ char *netname; /* server's netname */ }; -extern long do_sys_mount(const char *, const char *, char *, int, void *); extern dev_t get_unnamed_dev(void); extern void put_unnamed_dev(dev_t); extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *); @@ -727,7 +726,7 @@ linux_nfs_mount.hostname [255] = 0; putname (the_name); - return do_sys_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount); + return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount); } /* XXXXXXXXXXXXXXXXXXXX */ @@ -787,7 +786,7 @@ ret = PTR_ERR(dev_fname); if (IS_ERR(dev_fname)) goto out2; - ret = do_sys_mount(dev_fname, dir_page, type_page, linux_flags, NULL); + ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL); if (dev_fname) putname(dev_fname); out2: diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S --- v2.3.99-pre8/linux/arch/sparc64/kernel/systbls.S Wed Apr 26 16:34:07 2000 +++ linux/arch/sparc64/kernel/systbls.S Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: systbls.S,v 1.72 2000/04/13 07:30:34 jj Exp $ +/* $Id: systbls.S,v 1.73 2000/05/10 14:23:39 jj Exp $ * systbls.S: System call entry point tables for OS compatibility. * The native Linux system call table lives here also. * @@ -83,7 +83,7 @@ /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown, sys_mknod /*15*/ .word sys_chmod, sys_lchown, sparc_brk, sys_perfctr, sys_lseek /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid -/*25*/ .word sys_time, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall +/*25*/ .word sys_nis_syscall, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall /*30*/ .word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice .word sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile /*40*/ .word sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall @@ -124,7 +124,7 @@ .word sys_ipc, sys_nis_syscall, sys_clone, sys_nis_syscall, sys_adjtimex /*220*/ .word sys_nis_syscall, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid .word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid -/*230*/ .word sys_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall +/*230*/ .word sys_select, sys_nis_syscall, sys_nis_syscall, sys_stime, sys_nis_syscall .word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall /*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c --- v2.3.99-pre8/linux/arch/sparc64/kernel/time.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/kernel/time.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.25 2000/04/13 05:29:44 davem Exp $ +/* $Id: time.c,v 1.26 2000/05/09 17:40:14 davem Exp $ * time.c: UltraSparc timer and TOD clock support. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c --- v2.3.99-pre8/linux/arch/sparc64/kernel/traps.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/kernel/traps.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.65 2000/01/21 11:39:01 jj Exp $ +/* $Id: traps.c,v 1.66 2000/05/09 17:40:14 davem Exp $ * arch/sparc64/kernel/traps.c * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/ttable.S linux/arch/sparc64/kernel/ttable.S --- v2.3.99-pre8/linux/arch/sparc64/kernel/ttable.S Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/kernel/ttable.S Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: ttable.S,v 1.30 1999/12/01 23:52:03 davem Exp $ +/* $Id: ttable.S,v 1.31 2000/05/09 17:40:14 davem Exp $ * ttable.S: Sparc V9 Trap Table(s) with SpitFire extensions. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/lib/debuglocks.c linux/arch/sparc64/lib/debuglocks.c --- v2.3.99-pre8/linux/arch/sparc64/lib/debuglocks.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/lib/debuglocks.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: debuglocks.c,v 1.4 2000/01/31 04:59:10 davem Exp $ +/* $Id: debuglocks.c,v 1.5 2000/05/09 17:40:14 davem Exp $ * debuglocks.c: Debugging versions of SMP locking primitives. * * Copyright (C) 1998 David S. Miller (davem@redhat.com) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.3.99-pre8/linux/arch/sparc64/mm/init.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/mm/init.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.151 2000/04/26 17:09:32 davem Exp $ +/* $Id: init.c,v 1.152 2000/05/09 17:40:14 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S --- v2.3.99-pre8/linux/arch/sparc64/mm/ultra.S Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/mm/ultra.S Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: ultra.S,v 1.42 2000/05/05 18:47:41 davem Exp $ +/* $Id: ultra.S,v 1.43 2000/05/09 17:40:14 davem Exp $ * ultra.S: Don't expand these all over the place... * * Copyright (C) 1997, 2000 David S. Miller (davem@redhat.com) diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/prom/misc.c linux/arch/sparc64/prom/misc.c --- v2.3.99-pre8/linux/arch/sparc64/prom/misc.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/prom/misc.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.17 2000/04/15 06:02:50 davem Exp $ +/* $Id: misc.c,v 1.18 2000/05/09 17:40:14 davem Exp $ * misc.c: Miscellaneous prom functions that don't belong * anywhere else. * diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/solaris/misc.c linux/arch/sparc64/solaris/misc.c --- v2.3.99-pre8/linux/arch/sparc64/solaris/misc.c Thu May 11 15:30:06 2000 +++ linux/arch/sparc64/solaris/misc.c Mon May 22 09:50:54 2000 @@ -1,4 +1,4 @@ -/* $Id: misc.c,v 1.26 2000/04/14 09:59:02 davem Exp $ +/* $Id: misc.c,v 1.27 2000/05/09 17:40:14 davem Exp $ * misc.c: Miscelaneous syscall emulation for Solaris * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/acorn/net/Makefile linux/drivers/acorn/net/Makefile --- v2.3.99-pre8/linux/drivers/acorn/net/Makefile Thu Mar 2 14:36:22 2000 +++ linux/drivers/acorn/net/Makefile Mon May 15 12:00:34 2000 @@ -3,7 +3,7 @@ # Makefile for the Acorn ethercard network device drivers # -L_TARGET := acorn-net.a +O_TARGET := acorn-net.o MOD_LIST_NAME := ACORN_NET_MODULES obj-y := @@ -11,11 +11,11 @@ obj-n := obj- := -obj-$(CONFIG_ARM_ETHER1) += ether1.o -obj-$(CONFIG_ARM_ETHER3) += ether3.o obj-$(CONFIG_ARM_ETHERH) += etherh.o +obj-$(CONFIG_ARM_ETHER3) += ether3.o +obj-$(CONFIG_ARM_ETHER1) += ether1.o -L_OBJS := $(obj-y) +O_OBJS := $(obj-y) M_OBJS := $(obj-m) include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/acorn/net/ether1.c linux/drivers/acorn/net/ether1.c --- v2.3.99-pre8/linux/drivers/acorn/net/ether1.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/acorn/net/ether1.c Mon May 15 12:00:34 2000 @@ -29,6 +29,7 @@ * TDR time-distance. * 1.05 RMK 31/12/1997 Removed calls to dev_tint for 2.1 * 1.06 RMK 10/02/2000 Updated for 2.3.43 + * 1.07 RMK 13/05/2000 Updated for 2.3.99-pre8 */ #include @@ -74,7 +75,7 @@ static void ether1_timeout(struct net_device *dev); /* ------------------------------------------------------------------------- */ -static char *version = "ether1 ethernet driver (c) 2000 Russell King v1.06\n"; +static char *version = "ether1 ethernet driver (c) 2000 Russell King v1.07\n"; #define BUS_16 16 #define BUS_8 8 @@ -620,95 +621,6 @@ return failures ? 1 : 0; } -static int __init -ether1_probe1(struct net_device *dev) -{ - static unsigned int version_printed = 0; - struct ether1_priv *priv; - int i; - - if (!dev->priv) - dev->priv = kmalloc (sizeof (struct ether1_priv), GFP_KERNEL); - - if (!dev->priv) - return 1; - - priv = (struct ether1_priv *)dev->priv; - memset (priv, 0, sizeof (struct ether1_priv)); - - if ((priv->bus_type = ether1_reset (dev)) == 0) { - kfree (dev->priv); - return 1; - } - - if (net_debug && version_printed++ == 0) - printk (KERN_INFO "%s", version); - - request_region (dev->base_addr, 16, "ether1"); - request_region (dev->base_addr + 0x800, 4096, "ether1(ram)"); - - printk (KERN_INFO "%s: ether1 at %lx, IRQ%d, ether address ", - dev->name, dev->base_addr, dev->irq); - - for (i = 0; i < 6; i++) - printk (i==0?" %02x":i==5?":%02x\n":":%02x", dev->dev_addr[i]); - - if (ether1_init_2 (dev)) { - kfree (dev->priv); - return 1; - } - - dev->open = ether1_open; - dev->stop = ether1_close; - dev->hard_start_xmit = ether1_sendpacket; - dev->get_stats = ether1_getstats; - dev->set_multicast_list = ether1_setmulticastlist; - dev->tx_timeout = ether1_timeout; - dev->watchdog_timeo = 5 * HZ / 100; - - /* Fill in the fields of the device structure with ethernet values */ - ether_setup (dev); - - return 0; -} - -/* ------------------------------------------------------------------------- */ - -static void __init -ether1_addr(struct net_device *dev) -{ - int i; - - for (i = 0; i < 6; i++) - dev->dev_addr[i] = inb (IDPROM_ADDRESS + i); -} - -int __init -ether1_probe(struct net_device *dev) -{ -#ifndef MODULE - struct expansion_card *ec; - - if (!dev) - return ENODEV; - - ecard_startfind (); - if ((ec = ecard_find (0, ether1_cids)) == NULL) - return ENODEV; - - dev->base_addr = ecard_address (ec, ECARD_IOC, ECARD_FAST); - dev->irq = ec->irq; - - ecard_claim (ec); - -#endif - ether1_addr (dev); - - if (ether1_probe1 (dev) == 0) - return 0; - return ENODEV; -} - /* ------------------------------------------------------------------------- */ static int @@ -1087,66 +999,118 @@ /* ------------------------------------------------------------------------- */ -#ifdef MODULE +static void __init ether1_banner(void) +{ + static unsigned int version_printed = 0; -static struct ether_dev { - struct expansion_card *ec; - char name[9]; - struct net_device dev; -} ether_devs[MAX_ECARDS]; + if (net_debug && version_printed++ == 0) + printk (KERN_INFO "%s", version); +} -int -init_module (void) +static struct net_device * __init ether1_init_one(struct expansion_card *ec) { - struct expansion_card *ec; - int i, ret = -ENODEV; + struct net_device *dev; + struct ether1_priv *priv; + int i; - memset(ether_devs, 0, sizeof(ether_devs)); + ether1_banner(); - ecard_startfind (); - ec = ecard_find(0, ether1_cids); - i = 0; - - while (ec && i < MAX_ECARDS) { - ecard_claim(ec); - - ether_devs[i].ec = ec; - ether_devs[i].dev.irq = ec->irq; - ether_devs[i].dev.base_addr = ecard_address(ec, ECARD_IOC, ECARD_FAST); - ether_devs[i].dev.init = ether1_probe; - ether_devs[i].dev.name = ether_devs[i].name; - - ret = register_netdev(ðer_devs[i].dev); - - if (ret) { - ecard_release(ec); - ether_devs[i].ec = NULL; - break; - } + ecard_claim(ec); + + dev = init_etherdev(NULL, sizeof(struct ether1_priv)); + if (!dev) + goto out; - i += 1; - ec = ecard_find(0, ether1_cids); + dev->base_addr = ecard_address(ec, ECARD_IOC, ECARD_FAST); + dev->irq = ec->irq; + + /* + * these will not fail - the nature of the bus ensures this + */ + request_region(dev->base_addr, 16, dev->name); + request_region(dev->base_addr + 0x800, 4096, dev->name); + + priv = (struct ether1_priv *)dev->priv; + if ((priv->bus_type = ether1_reset(dev)) == 0) + goto free_dev; + + printk(KERN_INFO "%s: ether1 at %lx, IRQ%d, ether address ", + dev->name, dev->base_addr, dev->irq); + + for (i = 0; i < 6; i++) { + dev->dev_addr[i] = inb(IDPROM_ADDRESS + i); + printk (i==0?" %02x":i==5?":%02x\n":":%02x", dev->dev_addr[i]); } - return i != 0 ? 0 : ret; + if (ether1_init_2(dev)) + goto free_dev; + + dev->open = ether1_open; + dev->stop = ether1_close; + dev->hard_start_xmit = ether1_sendpacket; + dev->get_stats = ether1_getstats; + dev->set_multicast_list = ether1_setmulticastlist; + dev->tx_timeout = ether1_timeout; + dev->watchdog_timeo = 5 * HZ / 100; + return 0; + +free_dev: + release_region(dev->base_addr, 16); + release_region(dev->base_addr + 0x800, 4096); + unregister_netdev(dev); + kfree(dev); +out: + ecard_release(ec); + return dev; } -void -cleanup_module (void) +static struct expansion_card *e_card[MAX_ECARDS]; +static struct net_device *e_dev[MAX_ECARDS]; + +static int __init ether1_init(void) { - int i; + int i, ret = -ENODEV; + + ecard_startfind(); for (i = 0; i < MAX_ECARDS; i++) { - if (ether_devs[i].ec) { - unregister_netdev(ðer_devs[i].dev); + struct expansion_card *ec; + struct net_device *dev; + + ec = ecard_find(0, ether1_cids); + if (!ec) + break; - release_region(ether_devs[i].dev.base_addr, 16); - release_region(ether_devs[i].dev.base_addr + 0x800, 4096); + dev = ether1_init_one(ec); + if (!dev) + break; - ecard_release(ether_devs[i].ec); + e_card[i] = ec; + e_dev[i] = dev; + ret = 0; + } + + return ret; +} - ether_devs[i].ec = NULL; +static void __exit ether1_exit(void) +{ + int i; + + for (i = 0; i < MAX_ECARDS; i++) { + if (e_dev[i]) { + unregister_netdev(e_dev[i]); + release_region(e_dev[i]->base_addr, 16); + release_region(e_dev[i]->base_addr + 0x800, 4096); + kfree(e_dev[i]); + e_dev[i] = NULL; + } + if (e_card[i]) { + ecard_release(e_card[i]); + e_card[i] = NULL; } } } -#endif /* MODULE */ + +module_init(ether1_init); +module_exit(ether1_exit); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/acorn/net/ether3.c linux/drivers/acorn/net/ether3.c --- v2.3.99-pre8/linux/drivers/acorn/net/ether3.c Sun Feb 20 21:12:38 2000 +++ linux/drivers/acorn/net/ether3.c Mon May 15 12:00:34 2000 @@ -37,9 +37,10 @@ * 1.15 RMK 30/04/1999 More fixes to the transmit routine for buggy * hardware. * 1.16 RMK 10/02/2000 Updated for 2.3.43 + * 1.17 RMK 13/05/2000 Updated for 2.3.99-pre8 */ -static char *version = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.16\n"; +static char *version = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n"; #include #include @@ -78,7 +79,6 @@ static void ether3_setmulticastlist(struct net_device *dev); static int ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int maxcnt); static void ether3_tx(struct net_device *dev, struct dev_priv *priv); -static int ether3_probe1 (struct net_device *dev); static int ether3_open (struct net_device *dev); static int ether3_sendpacket (struct sk_buff *skb, struct net_device *dev); static void ether3_interrupt (int irq, void *dev_id, struct pt_regs *regs); @@ -407,132 +407,6 @@ } /* - * This is the real probe routine. - */ -static int __init -ether3_probe1(struct net_device *dev) -{ - static unsigned version_printed = 0; - struct dev_priv *priv; - unsigned int i, bus_type, error = ENODEV; - const char *name = "ether3"; - - if (net_debug && version_printed++ == 0) - printk(version); - - if (!dev->priv) { - dev->priv = kmalloc(sizeof (struct dev_priv), GFP_KERNEL); - if (!dev->priv) { - printk(KERN_ERR "ether3_probe1: no memory\n"); - return -ENOMEM; - } - } - - priv = (struct dev_priv *) dev->priv; - memset(priv, 0, sizeof(struct dev_priv)); - - request_region(dev->base_addr, 128, name); - - /* Reset card... - */ - ether3_outb(0x80, REG_CONFIG2 + 1); - bus_type = BUS_UNKNOWN; - udelay(4); - - /* Test using Receive Pointer (16-bit register) to find out - * how the ether3 is connected to the bus... - */ - if (ether3_probe_bus_8(dev, 0x100) && - ether3_probe_bus_8(dev, 0x201)) - bus_type = BUS_8; - - if (bus_type == BUS_UNKNOWN && - ether3_probe_bus_16(dev, 0x101) && - ether3_probe_bus_16(dev, 0x201)) - bus_type = BUS_16; - - switch (bus_type) { - case BUS_UNKNOWN: - printk(KERN_ERR "%s: unable to identify bus width\n", dev->name); - goto failed; - - case BUS_8: - printk(KERN_ERR "%s: %s found, but is an unsupported " - "8-bit card\n", dev->name, name); - goto failed; - - default: - break; - } - - printk("%s: %s at %lx, IRQ%d, ether address ", - dev->name, name, dev->base_addr, dev->irq); - for (i = 0; i < 6; i++) - printk(i == 5 ? "%2.2x\n" : "%2.2x:", dev->dev_addr[i]); - - if (ether3_init_2(dev)) - goto failed; - - dev->open = ether3_open; - dev->stop = ether3_close; - dev->hard_start_xmit = ether3_sendpacket; - dev->get_stats = ether3_getstats; - dev->set_multicast_list = ether3_setmulticastlist; - dev->tx_timeout = ether3_timeout; - dev->watchdog_timeo = 5 * HZ / 100; - - /* Fill in the fields of the device structure with ethernet values. */ - ether_setup(dev); - - return 0; - -failed: - kfree(dev->priv); - dev->priv = NULL; - release_region(dev->base_addr, 128); - return error; -} - -static void __init -ether3_get_dev(struct net_device *dev, struct expansion_card *ec) -{ - ecard_claim(ec); - - dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); - dev->irq = ec->irq; - - if (ec->cid.manufacturer == MANU_ANT && - ec->cid.product == PROD_ANT_ETHERB) { - dev->base_addr += 0x200; - } - - ec->irqaddr = (volatile unsigned char *)ioaddr(dev->base_addr); - ec->irqmask = 0xf0; - - ether3_addr(dev->dev_addr, ec); -} - -#ifndef MODULE -int __init -ether3_probe(struct net_device *dev) -{ - struct expansion_card *ec; - - if (!dev) - return ENODEV; - - ecard_startfind(); - - if ((ec = ecard_find(0, ether3_cids)) == NULL) - return ENODEV; - - ether3_get_dev(dev, ec); - - return ether3_probe1(dev); -} -#endif - -/* * Open/initialize the board. This is called (in the current kernel) * sometime after booting when the 'ifconfig' program is run. * @@ -903,63 +777,163 @@ } } -#ifdef MODULE +static void __init ether3_banner(void) +{ + static unsigned version_printed = 0; -static struct ether_dev { - struct expansion_card *ec; - char name[9]; - struct net_device dev; -} ether_devs[MAX_ECARDS]; + if (net_debug && version_printed++ == 0) + printk(version); +} -int -init_module(void) +static const char * __init +ether3_get_dev(struct net_device *dev, struct expansion_card *ec) { - struct expansion_card *ec; - int i, ret = -ENODEV; + const char *name = "ether3"; + dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); + dev->irq = ec->irq; + + if (ec->cid.manufacturer == MANU_ANT && + ec->cid.product == PROD_ANT_ETHERB) { + dev->base_addr += 0x200; + name = "etherb"; + } - memset(ether_devs, 0, sizeof(ether_devs)); + ec->irqaddr = (volatile unsigned char *)ioaddr(dev->base_addr); + ec->irqmask = 0xf0; - ecard_startfind (); - ec = ecard_find(0, ether3_cids); - i = 0; + ether3_addr(dev->dev_addr, ec); - while (ec && i < MAX_ECARDS) { - ecard_claim(ec); + return name; +} - ether_devs[i].ec = ec; - ether_devs[i].dev.init = ether3_probe1; - ether_devs[i].dev.name = ether_devs[i].name; - ether3_get_dev(ðer_devs[i].dev, ec); +static struct net_device * __init ether3_init_one(struct expansion_card *ec) +{ + struct net_device *dev; + struct dev_priv *priv; + const char *name; + int i, bus_type; - ret = register_netdev(ðer_devs[i].dev); + ether3_banner(); - if (ret) { - ecard_release(ec); - ether_devs[i].ec = NULL; - } else - i += 1; + ecard_claim(ec); - ec = ecard_find(0, ether3_cids); + dev = init_etherdev(NULL, sizeof(struct dev_priv)); + if (!dev) + goto out; + + name = ether3_get_dev(dev, ec); + + /* + * this will not fail - the nature of the bus ensures this + */ + request_region(dev->base_addr, 128, dev->name); + + priv = (struct dev_priv *) dev->priv; + + /* Reset card... + */ + ether3_outb(0x80, REG_CONFIG2 + 1); + bus_type = BUS_UNKNOWN; + udelay(4); + + /* Test using Receive Pointer (16-bit register) to find out + * how the ether3 is connected to the bus... + */ + if (ether3_probe_bus_8(dev, 0x100) && + ether3_probe_bus_8(dev, 0x201)) + bus_type = BUS_8; + + if (bus_type == BUS_UNKNOWN && + ether3_probe_bus_16(dev, 0x101) && + ether3_probe_bus_16(dev, 0x201)) + bus_type = BUS_16; + + switch (bus_type) { + case BUS_UNKNOWN: + printk(KERN_ERR "%s: unable to identify bus width\n", dev->name); + goto failed; + + case BUS_8: + printk(KERN_ERR "%s: %s found, but is an unsupported " + "8-bit card\n", dev->name, name); + goto failed; + + default: + break; } - return i != 0 ? 0 : ret; + printk("%s: %s at %lx, IRQ%d, ether address ", + dev->name, name, dev->base_addr, dev->irq); + for (i = 0; i < 6; i++) + printk(i == 5 ? "%2.2x\n" : "%2.2x:", dev->dev_addr[i]); + + if (ether3_init_2(dev)) + goto failed; + + dev->open = ether3_open; + dev->stop = ether3_close; + dev->hard_start_xmit = ether3_sendpacket; + dev->get_stats = ether3_getstats; + dev->set_multicast_list = ether3_setmulticastlist; + dev->tx_timeout = ether3_timeout; + dev->watchdog_timeo = 5 * HZ / 100; + return 0; + +failed: + release_region(dev->base_addr, 128); + unregister_netdev(dev); + kfree(dev); +out: + ecard_release(ec); + return NULL; } -void -cleanup_module(void) +static struct expansion_card *e_card[MAX_ECARDS]; +static struct net_device *e_dev[MAX_ECARDS]; + +static int ether3_init(void) { - int i; + int i, ret = -ENODEV; + + ecard_startfind(); for (i = 0; i < MAX_ECARDS; i++) { - if (ether_devs[i].ec) { - unregister_netdev(ðer_devs[i].dev); + struct net_device *dev; + struct expansion_card *ec; - release_region(ether_devs[i].dev.base_addr, 128); + ec = ecard_find(0, ether3_cids); + if (!ec) + break; - ecard_release(ether_devs[i].ec); + dev = ether3_init_one(ec); + if (!dev) + break; + + e_card[i] = ec; + e_dev[i] = dev; + ret = 0; + } + + return ret; +} - ether_devs[i].ec = NULL; +static void ether3_exit(void) +{ + int i; + + for (i = 0; i < MAX_ECARDS; i++) { + if (e_dev[i]) { + unregister_netdev(e_dev[i]); + release_region(e_dev[i]->base_addr, 128); + kfree(e_dev[i]); + e_dev[i] = NULL; + } + if (e_card[i]) { + ecard_release(e_card[i]); + e_card[i] = NULL; } } } -#endif /* MODULE */ + +module_init(ether3_init); +module_exit(ether3_exit); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/acorn/net/etherh.c linux/drivers/acorn/net/etherh.c --- v2.3.99-pre8/linux/drivers/acorn/net/etherh.c Sun Feb 20 21:12:38 2000 +++ linux/drivers/acorn/net/etherh.c Mon May 15 12:00:34 2000 @@ -14,6 +14,7 @@ * 23-11-1997 RMK 1.04 Added media autodetection * 16-04-1998 RMK 1.05 Improved media autodetection * 10-02-2000 RMK 1.06 Updated for 2.3.43 + * 13-05-2000 RMK 1.07 Updated for 2.3.99-pre8 * * Insmod Module Parameters * ------------------------ @@ -62,7 +63,8 @@ MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("i3 EtherH driver"); -static char *version = "etherh [500/600/600A] ethernet driver (c) 2000 R.M.King v1.06\n"; +static char *version __initdata = + "etherh [500/600/600A] ethernet driver (c) 2000 R.M.King v1.07\n"; #define ETHERH500_DATAPORT 0x200 /* MEMC */ #define ETHERH500_NS8390 0x000 /* MEMC */ @@ -81,34 +83,10 @@ /* --------------------------------------------------------------------------- */ -/* - * Read the ethernet address string from the on board rom. - * This is an ascii string... - */ -static int __init -etherh_addr(char *addr, struct expansion_card *ec) -{ - struct in_chunk_dir cd; - char *s; - - if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) { - int i; - for (i = 0; i < 6; i++) { - addr[i] = simple_strtoul(s + 1, &s, 0x10); - if (*s != (i == 5? ')' : ':')) - break; - } - if (i == 6) - return 0; - } - return ENODEV; -} - static void etherh_setif(struct net_device *dev) { - unsigned long addr; - unsigned long flags; + unsigned long addr, flags; save_flags_cli(flags); @@ -118,19 +96,27 @@ case PROD_I3_ETHERLAN600A: addr = dev->base_addr + EN0_RCNTHI; - if (ei_status.interface_num) /* 10b2 */ + switch (dev->if_port) { + case IF_PORT_10BASE2: outb((inb(addr) & 0xf8) | 1, addr); - else /* 10bT */ + break; + case IF_PORT_10BASET: outb((inb(addr) & 0xf8), addr); + break; + } break; case PROD_I3_ETHERLAN500: addr = dev->rmem_start; - if (ei_status.interface_num) /* 10b2 */ + switch (dev->if_port) { + case IF_PORT_10BASE2: outb(inb(addr) & ~ETHERH_CP_IF, addr); - else /* 10bT */ + break; + case IF_PORT_10BASET: outb(inb(addr) | ETHERH_CP_IF, addr); + break; + } break; default: @@ -143,22 +129,30 @@ static int etherh_getifstat(struct net_device *dev) { - int stat; + int stat = 0; switch (dev->mem_end) { case PROD_I3_ETHERLAN600: case PROD_I3_ETHERLAN600A: - if (ei_status.interface_num) /* 10b2 */ + switch (dev->if_port) { + case IF_PORT_10BASE2: stat = 1; - else /* 10bT */ + break; + case IF_PORT_10BASET: stat = inb(dev->base_addr+EN0_RCNTHI) & 4; + break; + } break; case PROD_I3_ETHERLAN500: - if (ei_status.interface_num) /* 10b2 */ + switch (dev->if_port) { + case IF_PORT_10BASE2: stat = 1; - else /* 10bT */ + break; + case IF_PORT_10BASET: stat = inb(dev->rmem_start) & ETHERH_CP_HEARTBEAT; + break; + } break; default: @@ -170,14 +164,54 @@ } /* - * Reset the 8390 (hard reset) + * Configure the interface. Note that we ignore the other + * parts of ifmap, since its mostly meaningless for this driver. + */ +static int etherh_set_config(struct net_device *dev, struct ifmap *map) +{ + switch (map->port) { + case IF_PORT_10BASE2: + case IF_PORT_10BASET: + /* + * If the user explicitly sets the interface + * media type, turn off automedia detection. + */ + dev->flags &= ~IFF_AUTOMEDIA; + dev->if_port = map->port; + break; + + default: + return -EINVAL; + } + + etherh_setif(dev); + + return 0; +} + +/* + * Reset the 8390 (hard reset). Note that we can't actually do this. */ static void etherh_reset(struct net_device *dev) { outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, dev->base_addr); - etherh_setif(dev); + /* + * See if we need to change the interface type. + * Note that we use 'interface_num' as a flag + * to indicate that we need to change the media. + */ + if (dev->flags & IFF_AUTOMEDIA && ei_status.interface_num) { + ei_status.interface_num = 0; + + if (dev->if_port == IF_PORT_10BASET) + dev->if_port = IF_PORT_10BASE2; + else + dev->if_port = IF_PORT_10BASET; + + etherh_setif(dev); + } } /* @@ -332,8 +366,31 @@ return -EAGAIN; } + /* + * Make sure that we aren't going to change the + * media type on the next reset - we are about to + * do automedia manually now. + */ + ei_status.interface_num = 0; + + /* + * If we are doing automedia detection, do it now. + * This is more reliable than the 8390's detection. + */ + if (dev->flags & IFF_AUTOMEDIA) { + dev->if_port = IF_PORT_10BASET; + etherh_setif(dev); + mdelay(1); + if (!etherh_getifstat(dev)) { + dev->if_port = IF_PORT_10BASE2; + etherh_setif(dev); + } + } else + etherh_setif(dev); + etherh_reset(dev); ei_open(dev); + return 0; } @@ -350,281 +407,266 @@ return 0; } +static void etherh_irq_enable(ecard_t *ec, int irqnr) +{ + unsigned int ctrl_addr = (unsigned int)ec->irq_data; + outb(inb(ctrl_addr) | ETHERH_CP_IE, ctrl_addr); +} + +static void etherh_irq_disable(ecard_t *ec, int irqnr) +{ + unsigned int ctrl_addr = (unsigned int)ec->irq_data; + outb(inb(ctrl_addr) & ~ETHERH_CP_IE, ctrl_addr); +} + +static expansioncard_ops_t etherh_ops = { + etherh_irq_enable, + etherh_irq_disable, + NULL, + NULL, + NULL, + NULL +}; + /* - * This is the real probe routine. + * Initialisation */ -static int __init -etherh_probe1(struct net_device *dev) + +static void __init etherh_banner(void) { static int version_printed; - unsigned int addr, i, reg0, tmp; - const char *dev_type; - const char *if_type; - const char *name = "etherh"; - - addr = dev->base_addr; if (net_debug && version_printed++ == 0) printk(version); +} - switch (dev->mem_end) { - case PROD_I3_ETHERLAN500: - dev_type = "500"; - break; - case PROD_I3_ETHERLAN600: - dev_type = "600"; - break; - case PROD_I3_ETHERLAN600A: - dev_type = "600A"; - break; - default: - dev_type = ""; - } +static int __init etherh_check_presence(struct net_device *dev) +{ + unsigned int addr = dev->base_addr, reg0, tmp; - reg0 = inb (addr); + reg0 = inb(addr); if (reg0 == 0xff) { if (net_debug & DEBUG_INIT) - printk("%s: %s error: NS8390 command register wrong\n", - dev->name, name); + printk("%s: etherh error: NS8390 command register wrong\n", + dev->name); return -ENODEV; } - outb (E8390_NODMA | E8390_PAGE1 | E8390_STOP, addr + E8390_CMD); - tmp = inb (addr + 13); - outb (0xff, addr + 13); - outb (E8390_NODMA | E8390_PAGE0, addr + E8390_CMD); - inb (addr + EN0_COUNTER0); - if (inb (addr + EN0_COUNTER0) != 0) { + outb(E8390_NODMA | E8390_PAGE1 | E8390_STOP, addr + E8390_CMD); + tmp = inb(addr + 13); + outb(0xff, addr + 13); + outb(E8390_NODMA | E8390_PAGE0, addr + E8390_CMD); + inb(addr + EN0_COUNTER0); + if (inb(addr + EN0_COUNTER0) != 0) { if (net_debug & DEBUG_INIT) - printk("%s: %s error: NS8390 not found\n", - dev->name, name); - outb (reg0, addr); - outb (tmp, addr + 13); + printk("%s: etherh error: NS8390 not found\n", + dev->name); + outb(reg0, addr); + outb(tmp, addr + 13); return -ENODEV; } - if (ethdev_init(dev)) - return -ENOMEM; - - request_region(addr, 16, name); - - printk("%s: %s %s at %lx, IRQ%d, ether address ", - dev->name, name, dev_type, dev->base_addr, dev->irq); - - for (i = 0; i < 6; i++) - printk (i == 5 ? "%2.2x " : "%2.2x:", dev->dev_addr[i]); - - ei_status.name = name; - ei_status.word16 = 1; - ei_status.tx_start_page = ETHERH_TX_START_PAGE; - ei_status.rx_start_page = ei_status.tx_start_page + TX_PAGES; - ei_status.stop_page = ETHERH_STOP_PAGE; - ei_status.reset_8390 = etherh_reset; - ei_status.block_input = etherh_block_input; - ei_status.block_output = etherh_block_output; - ei_status.get_8390_hdr = etherh_get_header; - dev->open = etherh_open; - dev->stop = etherh_close; - - /* select 10bT */ - ei_status.interface_num = 0; - if_type = "10BaseT"; - etherh_setif(dev); - mdelay(1); - if (!etherh_getifstat(dev)) { - if_type = "10Base2"; - ei_status.interface_num = 1; - etherh_setif(dev); - } - if (!etherh_getifstat(dev)) - if_type = "UNKNOWN"; - - printk("%s\n", if_type); - - etherh_reset(dev); - NS8390_init (dev, 0); return 0; } -static void etherh_irq_enable(ecard_t *ec, int irqnr) +/* + * Read the ethernet address string from the on board rom. + * This is an ascii string... + */ +static int __init etherh_addr(char *addr, struct expansion_card *ec) { - unsigned int ctrl_addr = (unsigned int)ec->irq_data; - outb(inb(ctrl_addr) | ETHERH_CP_IE, ctrl_addr); + struct in_chunk_dir cd; + char *s; + + if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) { + int i; + for (i = 0; i < 6; i++) { + addr[i] = simple_strtoul(s + 1, &s, 0x10); + if (*s != (i == 5? ')' : ':')) + break; + } + if (i == 6) + return 0; + } + return ENODEV; } -static void etherh_irq_disable(ecard_t *ec, int irqnr) +static struct net_device * __init etherh_init_one(struct expansion_card *ec) { - unsigned int ctrl_addr = (unsigned int)ec->irq_data; - outb(inb(ctrl_addr) & ~ETHERH_CP_IE, ctrl_addr); -} + struct net_device *dev; + const char *dev_type; + int i; -static expansioncard_ops_t etherh_ops = { - etherh_irq_enable, - etherh_irq_disable, - NULL, - NULL, - NULL, - NULL -}; + etherh_banner(); -static void __init -etherh_initdev(ecard_t *ec, struct net_device *dev) -{ - ecard_claim (ec); + ecard_claim(ec); - dev->irq = ec->irq; - dev->mem_end = ec->cid.product; + dev = init_etherdev(NULL, 0); + if (!dev) + goto out; + + etherh_addr(dev->dev_addr, ec); + + dev->open = etherh_open; + dev->stop = etherh_close; + dev->set_config = etherh_set_config; + dev->irq = ec->irq; + dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); + dev->mem_end = ec->cid.product; + ec->ops = ðerh_ops; switch (ec->cid.product) { case PROD_I3_ETHERLAN500: - dev->base_addr = ecard_address (ec, ECARD_MEMC, 0) + ETHERH500_NS8390; - dev->mem_start = dev->base_addr + ETHERH500_DATAPORT; + dev->base_addr += ETHERH500_NS8390; + dev->mem_start = dev->base_addr + ETHERH500_DATAPORT; dev->rmem_start = (unsigned long) - ec->irq_data = (void *)ecard_address (ec, ECARD_IOC, ECARD_FAST) + ec->irq_data = (void *)ecard_address (ec, ECARD_IOC, ECARD_FAST) + ETHERH500_CTRLPORT; break; case PROD_I3_ETHERLAN600: case PROD_I3_ETHERLAN600A: - dev->base_addr = ecard_address (ec, ECARD_MEMC, 0) + ETHERH600_NS8390; + dev->base_addr += ETHERH600_NS8390; dev->mem_start = dev->base_addr + ETHERH600_DATAPORT; - ec->irq_data = (void *)(dev->base_addr + ETHERH600_CTRLPORT); + ec->irq_data = (void *)(dev->base_addr + ETHERH600_CTRLPORT); break; default: - printk ("%s: etherh error: unknown card type\n", dev->name); + printk("%s: etherh error: unknown card type %x\n", + dev->name, ec->cid.product); + goto out; } - ec->ops = ðerh_ops; - etherh_addr(dev->dev_addr, ec); -} + if (!request_region(dev->base_addr, 16, dev->name)) + goto region_not_free; -#ifndef MODULE -int __init -etherh_probe(struct net_device *dev) -{ - if (!dev) - return ENODEV; + if (etherh_check_presence(dev) || ethdev_init(dev)) + goto release; - if (!dev->base_addr || dev->base_addr == 0xffe0) { - struct expansion_card *ec; + switch (ec->cid.product) { + case PROD_I3_ETHERLAN500: + dev_type = "500"; + break; - ecard_startfind(); + case PROD_I3_ETHERLAN600: + dev_type = "600"; + break; - if ((ec = ecard_find (0, etherh_cids)) == NULL) - return ENODEV; + case PROD_I3_ETHERLAN600A: + dev_type = "600A"; + break; - etherh_initdev(ec, dev); + default: + dev_type = "unknown"; + break; } - return etherh_probe1(dev); -} -#endif -#ifdef MODULE -#define MAX_ETHERH_CARDS 2 + printk("%s: etherh %s at %lx, IRQ%d, ether address ", + dev->name, dev_type, dev->base_addr, dev->irq); -static int io[MAX_ETHERH_CARDS]; -static int irq[MAX_ETHERH_CARDS]; -static char ethernames[MAX_ETHERH_CARDS][9]; -static struct net_device *my_ethers[MAX_ETHERH_CARDS]; -static struct expansion_card *ec[MAX_ETHERH_CARDS]; + for (i = 0; i < 6; i++) + printk(i == 5 ? "%2.2x\n" : "%2.2x:", dev->dev_addr[i]); -static int -init_all_cards(void) -{ - struct net_device *dev = NULL; - int i, found = 0; + /* + * Unfortunately, ethdev_init eventually calls + * ether_setup, which re-writes dev->flags. + */ + switch (ec->cid.product) { + case PROD_I3_ETHERLAN500: + dev->if_port = IF_PORT_UNKNOWN; + break; - for (i = 0; i < MAX_ETHERH_CARDS; i++) { - my_ethers[i] = NULL; - ec[i] = NULL; - strcpy (ethernames[i], " "); + case PROD_I3_ETHERLAN600: + case PROD_I3_ETHERLAN600A: + dev->flags |= IFF_PORTSEL | IFF_AUTOMEDIA; + dev->if_port = IF_PORT_10BASET; + break; } - ecard_startfind(); - - for (i = 0; i < MAX_ETHERH_CARDS; i++) { - if (!dev) - dev = (struct net_device *)kmalloc (sizeof (struct net_device), GFP_KERNEL); - if (dev) - memset (dev, 0, sizeof (struct net_device)); - - if (!io[i]) { - if ((ec[i] = ecard_find (0, etherh_cids)) == NULL) - continue; - - if (!dev) - return -ENOMEM; - - etherh_initdev (ec[i], dev); - } else { - ec[i] = NULL; - if (!dev) - return -ENOMEM; - dev->base_addr = io[i]; - dev->irq = irq[i]; - } + ei_status.name = dev->name; + ei_status.word16 = 1; + ei_status.tx_start_page = ETHERH_TX_START_PAGE; + ei_status.rx_start_page = ei_status.tx_start_page + TX_PAGES; + ei_status.stop_page = ETHERH_STOP_PAGE; - dev->init = etherh_probe1; - dev->name = ethernames[i]; + ei_status.reset_8390 = etherh_reset; + ei_status.block_input = etherh_block_input; + ei_status.block_output = etherh_block_output; + ei_status.get_8390_hdr = etherh_get_header; + ei_status.interface_num = 0; - my_ethers[i] = dev; + etherh_reset(dev); + NS8390_init(dev, 0); + return dev; - if (register_netdev(dev) != 0) { - printk(KERN_ERR "No etherh card found at %08lX\n", - dev->base_addr); - if (ec[i]) { - ecard_release(ec[i]); - ec[i] = NULL; - } - continue; - } - found ++; - dev = NULL; - } +release: + release_region(dev->base_addr, 16); +region_not_free: + unregister_netdev(dev); + kfree(dev); +out: + ecard_release(ec); + return NULL; +} - if (dev) - kfree (dev); +#define MAX_ETHERH_CARDS 2 - return found ? 0 : -ENODEV; -} +static struct net_device *e_dev[MAX_ETHERH_CARDS]; +static struct expansion_card *e_card[MAX_ETHERH_CARDS]; -int -init_module(void) +static int __init etherh_init(void) { - int ret; + int i, ret = -ENODEV; - if (load_8390_module(__FILE__)) + if (load_8390_module("etherh.c")) return -ENOSYS; lock_8390_module(); - ret = init_all_cards(); + ecard_startfind(); - if (ret) { - unlock_8390_module(); + for (i = 0; i < MAX_ECARDS; i++) { + struct expansion_card *ec; + struct net_device *dev; + + ec = ecard_find(0, etherh_cids); + if (!ec) + break; + + dev = etherh_init_one(ec); + if (!dev) + break; + + e_card[i] = ec; + e_dev[i] = dev; + ret = 0; } + if (ret) + unlock_8390_module(); + return ret; } -void -cleanup_module(void) +static void __exit etherh_exit(void) { int i; + for (i = 0; i < MAX_ETHERH_CARDS; i++) { - if (my_ethers[i]) { - unregister_netdev(my_ethers[i]); - release_region (my_ethers[i]->base_addr, 16); - kfree (my_ethers[i]); - my_ethers[i] = NULL; + if (e_dev[i]) { + unregister_netdev(e_dev[i]); + release_region(e_dev[i]->base_addr, 16); + kfree(e_dev[i]); + e_dev[i] = NULL; } - if (ec[i]) { - ec[i]->ops = NULL; - ecard_release(ec[i]); - ec[i] = NULL; + if (e_card[i]) { + e_card[i]->ops = NULL; + ecard_release(e_card[i]); + e_card[i] = NULL; } } unlock_8390_module(); } -#endif /* MODULE */ + +module_init(etherh_init); +module_exit(etherh_exit); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/atm/eni.c linux/drivers/atm/eni.c --- v2.3.99-pre8/linux/drivers/atm/eni.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/atm/eni.c Sat May 13 08:19:21 2000 @@ -2283,7 +2283,7 @@ 0, 0, 0 /* FPGA */ }, { PCI_VENDOR_ID_EF, PCI_DEVICE_ID_EF_ATM_ASIC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 /* ASIC */ }, - { 0 } + { 0, } }; MODULE_DEVICE_TABLE(pci,eni_pci_tbl); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/block/Config.in linux/drivers/block/Config.in --- v2.3.99-pre8/linux/drivers/block/Config.in Fri May 12 14:18:55 2000 +++ linux/drivers/block/Config.in Mon May 15 10:57:20 2000 @@ -49,10 +49,12 @@ bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD dep_tristate ' Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD -bool ' DANGEROUS! RAID1/RAID5 code' CONFIG_RAID15_DANGEROUS -if [ "$CONFIG_RAID15_DANGEROUS" = "y" ]; then - dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD - dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool ' RAID-1/RAID-5 code (DANGEROUS)' CONFIG_RAID15_DANGEROUS + if [ "$CONFIG_RAID15_DANGEROUS" = "y" ]; then + dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD + dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD + fi fi tristate 'RAM disk support' CONFIG_BLK_DEV_RAM dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c --- v2.3.99-pre8/linux/drivers/block/DAC960.c Thu May 11 15:30:06 2000 +++ linux/drivers/block/DAC960.c Sat May 13 07:35:38 2000 @@ -19,8 +19,9 @@ */ -#define DAC960_DriverVersion "2.3.4" -#define DAC960_DriverDate "23 September 1999" +#define DAC960_DriverVersion "2.3.5" +#define DAC960_DriverDate "23 January 2000" + #include @@ -110,7 +111,7 @@ DAC960_Announce("***** DAC960 RAID Driver Version " DAC960_DriverVersion " of " DAC960_DriverDate " *****\n", Controller); - DAC960_Announce("Copyright 1998-1999 by Leonard N. Zubkoff " + DAC960_Announce("Copyright 1998-2000 by Leonard N. Zubkoff " "\n", Controller); } @@ -184,6 +185,23 @@ /* + DAC960_WaitForCommand waits for a wake_up on Controller's Command Wait Queue. +*/ + +static void DAC960_WaitForCommand(DAC960_Controller_T *Controller) +{ + DECLARE_WAITQUEUE(WaitQueueEntry, current); + add_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry); + current->state = TASK_UNINTERRUPTIBLE; + spin_unlock(&io_request_lock); + schedule(); + current->state = TASK_RUNNING; + remove_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry); + spin_lock_irq(&io_request_lock); +} + + +/* DAC960_QueueCommand queues Command. */ @@ -307,6 +325,62 @@ /* + DAC960_ReportErrorStatus reports Controller BIOS Messages passed through + the Error Status Register when the driver performs the BIOS handshaking. + It returns true for fatal errors and false otherwise. +*/ + +static boolean DAC960_ReportErrorStatus(DAC960_Controller_T *Controller, + unsigned char ErrorStatus, + unsigned char Parameter0, + unsigned char Parameter1) +{ + switch (ErrorStatus) + { + case 0x00: + DAC960_Notice("Physical Drive %d:%d Not Responding\n", + Controller, Parameter1, Parameter0); + break; + case 0x08: + if (Controller->DriveSpinUpMessageDisplayed) break; + DAC960_Notice("Spinning Up Drives\n", Controller); + Controller->DriveSpinUpMessageDisplayed = true; + break; + case 0x30: + DAC960_Notice("Configuration Checksum Error\n", Controller); + break; + case 0x60: + DAC960_Notice("Mirror Race Recovery Failed\n", Controller); + break; + case 0x70: + DAC960_Notice("Mirror Race Recovery In Progress\n", Controller); + break; + case 0x90: + DAC960_Notice("Physical Drive %d:%d COD Mismatch\n", + Controller, Parameter1, Parameter0); + break; + case 0xA0: + DAC960_Notice("Logical Drive Installation Aborted\n", Controller); + break; + case 0xB0: + DAC960_Notice("Mirror Race On A Critical Logical Drive\n", Controller); + break; + case 0xD0: + DAC960_Notice("New Controller Configuration Found\n", Controller); + break; + case 0xF0: + DAC960_Error("Fatal Memory Parity Error for Controller at\n", Controller); + return true; + default: + DAC960_Error("Unknown Initialization Error %02X for Controller at\n", + Controller, ErrorStatus); + return true; + } + return false; +} + + +/* DAC960_EnableMemoryMailboxInterface enables the Memory Mailbox Interface. */ @@ -372,7 +446,7 @@ case DAC960_V5_Controller: while (--TimeoutCounter >= 0) { - if (DAC960_V5_HardwareMailboxEmptyP(ControllerBaseAddress)) + if (!DAC960_V5_HardwareMailboxFullP(ControllerBaseAddress)) break; udelay(10); } @@ -469,6 +543,9 @@ unsigned long BaseAddress1 = pci_resource_start (PCI_Device, 1); unsigned short SubsystemVendorID, SubsystemDeviceID; int CommandIdentifier; + unsigned char ErrorStatus, Parameter0, Parameter1; + void *BaseAddress; + if (pci_enable_device(PCI_Device)) goto Ignore; @@ -517,24 +594,6 @@ Controller->Function = Function; sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber); /* - Acquire shared access to the IRQ Channel. - */ - if (IRQ_Channel == 0) - { - DAC960_Error("IRQ Channel %d illegal for Controller at\n", - Controller, IRQ_Channel); - goto Failure; - } - strcpy(Controller->FullModelName, "DAC960"); - if (request_irq(IRQ_Channel, DAC960_InterruptHandler, - SA_SHIRQ, Controller->FullModelName, Controller) < 0) - { - DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n", - Controller, IRQ_Channel); - goto Failure; - } - Controller->IRQ_Channel = IRQ_Channel; - /* Map the Controller Register Window. */ if (MemoryWindowSize < PAGE_SIZE) @@ -549,34 +608,87 @@ "Controller at\n", Controller); goto Failure; } + BaseAddress = Controller->BaseAddress; switch (ControllerType) { case DAC960_V5_Controller: - DAC960_V5_DisableInterrupts(Controller->BaseAddress); + DAC960_V5_DisableInterrupts(BaseAddress); + DAC960_V5_AcknowledgeHardwareMailboxStatus(BaseAddress); + udelay(1000); + while (DAC960_V5_InitializationInProgressP(BaseAddress)) + { + if (DAC960_V5_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } if (!DAC960_EnableMemoryMailboxInterface(Controller)) { DAC960_Error("Unable to Enable Memory Mailbox Interface " "for Controller at\n", Controller); goto Failure; } - DAC960_V5_EnableInterrupts(Controller->BaseAddress); + DAC960_V5_EnableInterrupts(BaseAddress); break; case DAC960_V4_Controller: - DAC960_V4_DisableInterrupts(Controller->BaseAddress); + DAC960_V4_DisableInterrupts(BaseAddress); + DAC960_V4_AcknowledgeHardwareMailboxStatus(BaseAddress); + udelay(1000); + while (DAC960_V4_InitializationInProgressP(BaseAddress)) + { + if (DAC960_V4_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } if (!DAC960_EnableMemoryMailboxInterface(Controller)) { DAC960_Error("Unable to Enable Memory Mailbox Interface " "for Controller at\n", Controller); goto Failure; } - DAC960_V4_EnableInterrupts(Controller->BaseAddress); + DAC960_V4_EnableInterrupts(BaseAddress); break; case DAC960_V3_Controller: request_region(Controller->IO_Address, 0x80, Controller->FullModelName); - DAC960_V3_EnableInterrupts(Controller->BaseAddress); + DAC960_V3_DisableInterrupts(BaseAddress); + DAC960_V3_AcknowledgeStatus(BaseAddress); + udelay(1000); + while (DAC960_V3_InitializationInProgressP(BaseAddress)) + { + if (DAC960_V3_ReadErrorStatus(BaseAddress, &ErrorStatus, + &Parameter0, &Parameter1) && + DAC960_ReportErrorStatus(Controller, ErrorStatus, + Parameter0, Parameter1)) + goto Failure; + udelay(10); + } + DAC960_V3_EnableInterrupts(BaseAddress); break; } + /* + Acquire shared access to the IRQ Channel. + */ + if (IRQ_Channel == 0) + { + DAC960_Error("IRQ Channel %d illegal for Controller at\n", + Controller, IRQ_Channel); + goto Failure; + } + strcpy(Controller->FullModelName, "DAC960"); + if (request_irq(IRQ_Channel, DAC960_InterruptHandler, + SA_SHIRQ, Controller->FullModelName, Controller) < 0) + { + DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n", + Controller, IRQ_Channel); + goto Failure; + } + Controller->IRQ_Channel = IRQ_Channel; DAC960_ActiveControllerCount++; for (CommandIdentifier = 0; CommandIdentifier < DAC960_MaxChannels; @@ -597,11 +709,11 @@ "0x%X PCI Address 0x%X\n", Controller, Bus, Device, Function, IO_Address, PCI_Address); if (Controller == NULL) break; - if (Controller->IRQ_Channel > 0) - free_irq(IRQ_Channel, Controller); if (Controller->MemoryMappedAddress != NULL) iounmap(Controller->MemoryMappedAddress); DAC960_Controllers[Controller->ControllerNumber] = NULL; + if (Controller->IRQ_Channel > 0) + free_irq(IRQ_Channel, Controller); Ignore: kfree(Controller); } @@ -1346,9 +1458,7 @@ Command = DAC960_AllocateCommand(Controller); if (Command != NULL) break; if (!WaitForCommand) return false; - spin_unlock(&io_request_lock); - sleep_on(&Controller->CommandWaitQueue); - spin_lock_irq(&io_request_lock); + DAC960_WaitForCommand(Controller); } DAC960_ClearCommand(Command); if (Request->cmd == READ) @@ -1900,6 +2010,20 @@ } else if (NewEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress) Controller->NeedConsistencyCheckProgress = true; + if (CommandType != DAC960_MonitoringCommand && + Controller->RebuildFlagPending) + { + DAC960_Enquiry_T *Enquiry = (DAC960_Enquiry_T *) + Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress); + Enquiry->RebuildFlag = Controller->PendingRebuildFlag; + Controller->RebuildFlagPending = false; + } + else if (CommandType == DAC960_MonitoringCommand && + NewEnquiry->RebuildFlag > DAC960_BackgroundCheckInProgress) + { + Controller->PendingRebuildFlag = NewEnquiry->RebuildFlag; + Controller->RebuildFlagPending = true; + } } else if (CommandOpcode == DAC960_PerformEventLogOperation) { @@ -2083,6 +2207,9 @@ Controller->RebuildProgress.LogicalDriveSize; unsigned int BlocksCompleted = LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks; + if (CommandStatus == DAC960_NoRebuildOrCheckInProgress && + Controller->LastRebuildStatus == DAC960_NormalCompletion) + CommandStatus = DAC960_RebuildSuccessful; switch (CommandStatus) { case DAC960_NormalCompletion: @@ -2110,13 +2237,28 @@ "Failure of Drive Being Rebuilt\n", Controller); break; case DAC960_NoRebuildOrCheckInProgress: - if (Controller->LastRebuildStatus != DAC960_NormalCompletion) - break; + break; case DAC960_RebuildSuccessful: DAC960_Progress("Rebuild Completed Successfully\n", Controller); break; + case DAC960_RebuildSuccessfullyTerminated: + DAC960_Progress("Rebuild Successfully Terminated\n", Controller); + break; } Controller->LastRebuildStatus = CommandStatus; + if (CommandType != DAC960_MonitoringCommand && + Controller->RebuildStatusPending) + { + Command->CommandStatus = Controller->PendingRebuildStatus; + Controller->RebuildStatusPending = false; + } + else if (CommandType == DAC960_MonitoringCommand && + CommandStatus != DAC960_NormalCompletion && + CommandStatus != DAC960_NoRebuildOrCheckInProgress) + { + Controller->PendingRebuildStatus = CommandStatus; + Controller->RebuildStatusPending = true; + } } else if (CommandOpcode == DAC960_RebuildStat) { @@ -2331,7 +2473,7 @@ if (CommandType == DAC960_QueuedCommand) { DAC960_KernelCommand_T *KernelCommand = Command->KernelCommand; - KernelCommand->CommandStatus = CommandStatus; + KernelCommand->CommandStatus = Command->CommandStatus; Command->KernelCommand = NULL; if (CommandOpcode == DAC960_DCDB) Controller->DirectCommandActive[KernelCommand->DCDB->Channel] @@ -2352,9 +2494,12 @@ return; } /* - Deallocate the Command, and wake up any processes waiting on a free Command. + Deallocate the Command. */ DAC960_DeallocateCommand(Command); + /* + Wake up any processes waiting on a free Command. + */ wake_up(&Controller->CommandWaitQueue); } @@ -2761,19 +2906,14 @@ } if (CommandOpcode == DAC960_DCDB) { - while (true) - { - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - if (!Controller->DirectCommandActive[DCDB.Channel] - [DCDB.TargetID]) - Command = DAC960_AllocateCommand(Controller); - if (Command != NULL) - Controller->DirectCommandActive[DCDB.Channel] - [DCDB.TargetID] = true; - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - if (Command != NULL) break; - sleep_on(&Controller->CommandWaitQueue); - } + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + while (Controller->DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] || + (Command = DAC960_AllocateCommand(Controller)) == NULL) + DAC960_WaitForCommand(Controller); + Controller->DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] = true; + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); DAC960_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox, @@ -2783,14 +2923,10 @@ } else { - while (true) - { - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - Command = DAC960_AllocateCommand(Controller); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - if (Command != NULL) break; - sleep_on(&Controller->CommandWaitQueue); - } + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + while ((Command = DAC960_AllocateCommand(Controller)) == NULL) + DAC960_WaitForCommand(Controller); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); DAC960_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox, @@ -3194,14 +3330,10 @@ DAC960_CommandMailbox_T *CommandMailbox; ProcessorFlags_T ProcessorFlags; unsigned char Channel, TargetID, LogicalDriveNumber; - while (true) - { - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - Command = DAC960_AllocateCommand(Controller); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - if (Command != NULL) break; - sleep_on(&Controller->CommandWaitQueue); - } + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + while ((Command = DAC960_AllocateCommand(Controller)) == NULL) + DAC960_WaitForCommand(Controller); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); Controller->UserStatusLength = 0; DAC960_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/block/DAC960.h linux/drivers/block/DAC960.h --- v2.3.99-pre8/linux/drivers/block/DAC960.h Tue Dec 14 01:27:23 1999 +++ linux/drivers/block/DAC960.h Sat May 20 10:55:25 2000 @@ -55,17 +55,17 @@ /* - Define a 32 bit I/O Address data type. + Define a 32/64 bit I/O Address data type. */ -typedef unsigned int DAC960_IO_Address_T; +typedef unsigned long DAC960_IO_Address_T; /* - Define a 32 bit PCI Bus Address data type. + Define a 32/64 bit PCI Bus Address data type. */ -typedef unsigned int DAC960_PCI_Address_T; +typedef unsigned long DAC960_PCI_Address_T; /* @@ -196,6 +196,7 @@ #define DAC960_RebuildFailed_BadBlocksOnOther 0x0003 /* Consistency */ #define DAC960_RebuildFailed_NewDriveFailed 0x0004 /* Consistency */ #define DAC960_RebuildSuccessful 0x0100 /* Consistency */ +#define DAC960_RebuildSuccessfullyTerminated 0x0107 /* Consistency */ #define DAC960_AddCapacityInProgress 0x0004 /* Consistency */ #define DAC960_AddCapacityFailedOrSuspended 0x00F4 /* Consistency */ #define DAC960_Config2ChecksumError 0x0002 /* Configuration */ @@ -513,7 +514,7 @@ unsigned char SynchronousMultiplier; /* Byte 4 */ unsigned char SynchronousOffset:5; /* Byte 5 Bits 0-4 */ unsigned char :3; /* Byte 5 Bits 5-7 */ - unsigned long DiskSize __attribute__ ((packed)); /* Bytes 6-9 */ + unsigned int DiskSize __attribute__ ((packed)); /* Bytes 6-9 */ } DAC960_DeviceState_T; @@ -1110,7 +1111,6 @@ typedef struct buffer_head BufferHeader_T; typedef struct file File_T; -typedef struct file_operations FileOperations_T; typedef struct gendisk GenericDiskInfo_T; typedef struct hd_geometry DiskGeometry_T; typedef struct hd_struct DiskPartition_T; @@ -1212,6 +1212,7 @@ unsigned char LogicalDriveCount; unsigned char GeometryTranslationHeads; unsigned char GeometryTranslationSectors; + unsigned char PendingRebuildFlag; unsigned short ControllerQueueDepth; unsigned short DriverQueueDepth; unsigned short MaxBlocksPerCommand; @@ -1247,6 +1248,9 @@ boolean NeedRebuildProgress; boolean NeedConsistencyCheckProgress; boolean EphemeralProgressMessage; + boolean RebuildFlagPending; + boolean RebuildStatusPending; + boolean DriveSpinUpMessageDisplayed; Timer_T MonitoringTimer; GenericDiskInfo_T GenericDiskInfo; DAC960_Command_T *FreeCommands; @@ -1265,6 +1269,7 @@ DAC960_EventLogEntry_T EventLogEntry; DAC960_RebuildProgress_T RebuildProgress; DAC960_CommandStatus_T LastRebuildStatus; + DAC960_CommandStatus_T PendingRebuildStatus; DAC960_LogicalDriveInformation_T LogicalDriveInformation[2][DAC960_MaxLogicalDrives]; DAC960_LogicalDriveState_T LogicalDriveInitialState[DAC960_MaxLogicalDrives]; @@ -1389,7 +1394,8 @@ DAC960_V5_MailboxRegister11Offset = 0x5B, DAC960_V5_MailboxRegister12Offset = 0x5C, DAC960_V5_StatusCommandIdentifierRegOffset = 0x5D, - DAC960_V5_StatusRegisterOffset = 0x5E + DAC960_V5_StatusRegisterOffset = 0x5E, + DAC960_V5_ErrorStatusRegisterOffset = 0x63 } DAC960_V5_RegisterOffsets_T; @@ -1411,7 +1417,8 @@ } Write; struct { boolean HardwareMailboxEmpty:1; /* Bit 0 */ - unsigned char :7; /* Bits 1-7 */ + boolean InitializationNotInProgress:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ } Read; } DAC960_V5_InboundDoorBellRegister_T; @@ -1455,6 +1462,22 @@ /* + Define the structure of the DAC960 V5 Error Status Register. +*/ + +typedef union DAC960_V5_ErrorStatusRegister +{ + unsigned char All; + struct { + unsigned int :2; /* Bits 0-1 */ + boolean ErrorStatusPending:1; /* Bit 2 */ + unsigned int :5; /* Bits 3-7 */ + } Bits; +} +DAC960_V5_ErrorStatusRegister_T; + + +/* Define inline functions to provide an abstraction for reading and writing the DAC960 V5 Controller Interface Registers. */ @@ -1510,12 +1533,21 @@ } static inline -boolean DAC960_V5_HardwareMailboxEmptyP(void *ControllerBaseAddress) +boolean DAC960_V5_HardwareMailboxFullP(void *ControllerBaseAddress) { DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; InboundDoorBellRegister.All = readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); - return InboundDoorBellRegister.Read.HardwareMailboxEmpty; + return !InboundDoorBellRegister.Read.HardwareMailboxEmpty; +} + +static inline +boolean DAC960_V5_InitializationInProgressP(void *ControllerBaseAddress) +{ + DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset); + return !InboundDoorBellRegister.Read.InitializationNotInProgress; } static inline @@ -1571,7 +1603,7 @@ void DAC960_V5_EnableInterrupts(void *ControllerBaseAddress) { DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister; - InterruptMaskRegister.All = 0; + InterruptMaskRegister.All = 0xFF; InterruptMaskRegister.Bits.DisableInterrupts = false; writeb(InterruptMaskRegister.All, ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset); @@ -1581,7 +1613,7 @@ void DAC960_V5_DisableInterrupts(void *ControllerBaseAddress) { DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister; - InterruptMaskRegister.All = 0; + InterruptMaskRegister.All = 0xFF; InterruptMaskRegister.Bits.DisableInterrupts = true; writeb(InterruptMaskRegister.All, ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset); @@ -1603,7 +1635,9 @@ NextCommandMailbox->Words[1] = CommandMailbox->Words[1]; NextCommandMailbox->Words[2] = CommandMailbox->Words[2]; NextCommandMailbox->Words[3] = CommandMailbox->Words[3]; + wmb(); NextCommandMailbox->Words[0] = CommandMailbox->Words[0]; + mb(); } static inline @@ -1633,6 +1667,26 @@ return readw(ControllerBaseAddress + DAC960_V5_StatusRegisterOffset); } +static inline boolean +DAC960_V5_ReadErrorStatus(void *ControllerBaseAddress, + unsigned char *ErrorStatus, + unsigned char *Parameter0, + unsigned char *Parameter1) +{ + DAC960_V5_ErrorStatusRegister_T ErrorStatusRegister; + ErrorStatusRegister.All = + readb(ControllerBaseAddress + DAC960_V5_ErrorStatusRegisterOffset); + if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; + ErrorStatusRegister.Bits.ErrorStatusPending = false; + *ErrorStatus = ErrorStatusRegister.All; + *Parameter0 = + readb(ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset); + *Parameter1 = + readb(ControllerBaseAddress + DAC960_V5_CommandIdentifierRegisterOffset); + writeb(0xFF, ControllerBaseAddress + DAC960_V5_ErrorStatusRegisterOffset); + return true; +} + static inline void DAC960_V5_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) { @@ -1691,7 +1745,8 @@ DAC960_V4_MailboxRegister11Offset = 0x100B, DAC960_V4_MailboxRegister12Offset = 0x100C, DAC960_V4_StatusCommandIdentifierRegOffset = 0x1018, - DAC960_V4_StatusRegisterOffset = 0x101A + DAC960_V4_StatusRegisterOffset = 0x101A, + DAC960_V4_ErrorStatusRegisterOffset = 0x103F } DAC960_V4_RegisterOffsets_T; @@ -1713,7 +1768,8 @@ } Write; struct { boolean HardwareMailboxFull:1; /* Bit 0 */ - unsigned int :31; /* Bits 1-31 */ + boolean InitializationInProgress:1; /* Bit 1 */ + unsigned int :30; /* Bits 2-31 */ } Read; } DAC960_V4_InboundDoorBellRegister_T; @@ -1758,6 +1814,22 @@ /* + Define the structure of the DAC960 V4 Error Status Register. +*/ + +typedef union DAC960_V4_ErrorStatusRegister +{ + unsigned char All; + struct { + unsigned int :2; /* Bits 0-1 */ + boolean ErrorStatusPending:1; /* Bit 2 */ + unsigned int :5; /* Bits 3-7 */ + } Bits; +} +DAC960_V4_ErrorStatusRegister_T; + + +/* Define inline functions to provide an abstraction for reading and writing the DAC960 V4 Controller Interface Registers. */ @@ -1822,6 +1894,15 @@ } static inline +boolean DAC960_V4_InitializationInProgressP(void *ControllerBaseAddress) +{ + DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readl(ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset); + return InboundDoorBellRegister.Read.InitializationInProgress; +} + +static inline void DAC960_V4_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress) { DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister; @@ -1910,7 +1991,9 @@ NextCommandMailbox->Words[1] = CommandMailbox->Words[1]; NextCommandMailbox->Words[2] = CommandMailbox->Words[2]; NextCommandMailbox->Words[3] = CommandMailbox->Words[3]; + wmb(); NextCommandMailbox->Words[0] = CommandMailbox->Words[0]; + mb(); } static inline @@ -1940,11 +2023,31 @@ return readw(ControllerBaseAddress + DAC960_V4_StatusRegisterOffset); } +static inline boolean +DAC960_V4_ReadErrorStatus(void *ControllerBaseAddress, + unsigned char *ErrorStatus, + unsigned char *Parameter0, + unsigned char *Parameter1) +{ + DAC960_V4_ErrorStatusRegister_T ErrorStatusRegister; + ErrorStatusRegister.All = + readb(ControllerBaseAddress + DAC960_V4_ErrorStatusRegisterOffset); + if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; + ErrorStatusRegister.Bits.ErrorStatusPending = false; + *ErrorStatus = ErrorStatusRegister.All; + *Parameter0 = + readb(ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset); + *Parameter1 = + readb(ControllerBaseAddress + DAC960_V4_CommandIdentifierRegisterOffset); + writeb(0, ControllerBaseAddress + DAC960_V4_ErrorStatusRegisterOffset); + return true; +} + static inline void DAC960_V4_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller) { void *ControllerBaseAddress = Controller->BaseAddress; - writel(0xAABBFFFF, + writel(0x743C485E, ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset); writel((unsigned long) Controller->FirstCommandMailbox, ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset); @@ -1962,7 +2065,7 @@ { void *ControllerBaseAddress = Controller->BaseAddress; if (readl(ControllerBaseAddress - + DAC960_V4_CommandOpcodeRegisterOffset) != 0xAABBFFFF) + + DAC960_V4_CommandOpcodeRegisterOffset) != 0x743C485E) return; *MemoryMailboxAddress = (void *) readl(ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset); @@ -1996,6 +2099,7 @@ DAC960_V3_MailboxRegister12Offset = 0x0C, DAC960_V3_StatusCommandIdentifierRegOffset = 0x0D, DAC960_V3_StatusRegisterOffset = 0x0E, + DAC960_V3_ErrorStatusRegisterOffset = 0x3F, DAC960_V3_InboundDoorBellRegisterOffset = 0x40, DAC960_V3_OutboundDoorBellRegisterOffset = 0x41, DAC960_V3_InterruptEnableRegisterOffset = 0x43 @@ -2019,7 +2123,8 @@ } Write; struct { boolean MailboxFull:1; /* Bit 0 */ - unsigned char :7; /* Bits 1-7 */ + boolean InitializationInProgress:1; /* Bit 1 */ + unsigned char :6; /* Bits 2-7 */ } Read; } DAC960_V3_InboundDoorBellRegister_T; @@ -2060,6 +2165,22 @@ /* + Define the structure of the DAC960 V3 Error Status Register. +*/ + +typedef union DAC960_V3_ErrorStatusRegister +{ + unsigned char All; + struct { + unsigned int :2; /* Bits 0-1 */ + boolean ErrorStatusPending:1; /* Bit 2 */ + unsigned int :5; /* Bits 3-7 */ + } Bits; +} +DAC960_V3_ErrorStatusRegister_T; + + +/* Define inline functions to provide an abstraction for reading and writing the DAC960 V3 Controller Interface Registers. */ @@ -2114,6 +2235,15 @@ } static inline +boolean DAC960_V3_InitializationInProgressP(void *ControllerBaseAddress) +{ + DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister; + InboundDoorBellRegister.All = + readb(ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset); + return InboundDoorBellRegister.Read.InitializationInProgress; +} + +static inline void DAC960_V3_AcknowledgeInterrupt(void *ControllerBaseAddress) { DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister; @@ -2186,6 +2316,26 @@ DAC960_V3_ReadStatusRegister(void *ControllerBaseAddress) { return readw(ControllerBaseAddress + DAC960_V3_StatusRegisterOffset); +} + +static inline boolean +DAC960_V3_ReadErrorStatus(void *ControllerBaseAddress, + unsigned char *ErrorStatus, + unsigned char *Parameter0, + unsigned char *Parameter1) +{ + DAC960_V3_ErrorStatusRegister_T ErrorStatusRegister; + ErrorStatusRegister.All = + readb(ControllerBaseAddress + DAC960_V3_ErrorStatusRegisterOffset); + if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false; + ErrorStatusRegister.Bits.ErrorStatusPending = false; + *ErrorStatus = ErrorStatusRegister.All; + *Parameter0 = + readb(ControllerBaseAddress + DAC960_V3_CommandOpcodeRegisterOffset); + *Parameter1 = + readb(ControllerBaseAddress + DAC960_V3_CommandIdentifierRegisterOffset); + writeb(0, ControllerBaseAddress + DAC960_V3_ErrorStatusRegisterOffset); + return true; } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/block/elevator.c linux/drivers/block/elevator.c --- v2.3.99-pre8/linux/drivers/block/elevator.c Tue Mar 14 19:10:39 2000 +++ linux/drivers/block/elevator.c Sat May 20 11:36:59 2000 @@ -105,7 +105,7 @@ int ret; blkelv_ioctl_arg_t output; - output.queue_ID = elevator; + output.queue_ID = elevator->queue_ID; output.read_latency = elevator->read_latency; output.write_latency = elevator->write_latency; output.max_bomb_segments = elevator->max_bomb_segments; @@ -146,5 +146,8 @@ void elevator_init(elevator_t * elevator) { + static unsigned int queue_ID; + *elevator = ELEVATOR_DEFAULTS; + elevator->queue_ID = queue_ID++; } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.3.99-pre8/linux/drivers/block/floppy.c Thu May 11 15:30:06 2000 +++ linux/drivers/block/floppy.c Mon May 22 09:50:55 2000 @@ -1,5 +1,5 @@ /* - * linux/kernel/floppy.c + * linux/drivers/block/floppy.c * * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1993, 1994 Alain Knaff @@ -96,6 +96,12 @@ * 1995/10/18 -- Ralf Baechle -- Portability cleanup; move machine dependent * features to asm/floppy.h. */ + +/* + * 1998/05/07 -- Russell King -- More portability cleanups; moved definition of + * interrupt and dma channel to asm/floppy.h. Cleaned up some formatting & + * use of '0' for NULL. + */ /* * 1998/06/07 -- Alan Cox -- Merged the 2.0.34 fixes for resource allocation @@ -123,19 +129,6 @@ /* do print messages for unexpected interrupts */ static int print_unex=1; #include - -/* the following is the mask of allowed drives. By default units 2 and - * 3 of both floppy controllers are disabled, because switching on the - * motor of these drives causes system hangs on some PCI computers. drive - * 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if - * a drive is allowed. */ - -static int FLOPPY_IRQ=6; -static int FLOPPY_DMA=2; -static int allowed_drive_mask = 0x33; -static int irqdma_allocated = 0; - - #include #include #include @@ -177,6 +170,8 @@ #include #include +static int FLOPPY_IRQ=6; +static int FLOPPY_DMA=2; static int can_use_virtual_dma=2; /* ======= * can use virtual DMA: @@ -186,7 +181,7 @@ * but fall back on virtual DMA when not enough memory available */ -static int use_virtual_dma=0; +static int use_virtual_dma; /* ======= * use virtual DMA * 0 using hard DMA @@ -205,8 +200,22 @@ static devfs_handle_t devfs_handle = NULL; #define K_64 0x10000 /* 64KB */ + +/* the following is the mask of allowed drives. By default units 2 and + * 3 of both floppy controllers are disabled, because switching on the + * motor of these drives causes system hangs on some PCI computers. drive + * 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if + * a drive is allowed. + * + * NOTE: This must come before we include the arch floppy header because + * some ports reference this variable from there. -DaveM + */ + +static int allowed_drive_mask = 0x33; + #include +static int irqdma_allocated = 0; #define MAJOR_NR FLOPPY_MAJOR @@ -231,9 +240,9 @@ static inline void fallback_on_nodma_alloc(char **addr, size_t l) { #ifdef FLOPPY_CAN_FALLBACK_ON_NODMA - if(*addr) + if (*addr) return; /* we have the memory */ - if(can_use_virtual_dma != 2) + if (can_use_virtual_dma != 2) return; /* no fallback allowed */ printk("DMA memory shortage. Temporarily falling back on virtual DMA\n"); *addr = (char *) nodma_mem_alloc(l); @@ -393,6 +402,16 @@ * 'options'. Other parameters should be self-explanatory (see also * setfdprm(8)). */ +/* + Size + | Sectors per track + | | Head + | | | Tracks + | | | | Stretch + | | | | | Gap 1 size + | | | | | | Data rate, | 0x40 for perp + | | | | | | | Spec1 (stepping rate, head unload + | | | | | | | | /fmt gap (gap2) */ static struct floppy_struct floppy_type[32] = { { 0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL }, /* 0 no testing */ { 720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"d360" }, /* 1 360KB PC */ @@ -403,7 +422,7 @@ { 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,"h720" }, /* 6 720KB AT */ { 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"H1440" }, /* 7 1.44MB 3.5" */ { 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"E2880" }, /* 8 2.88MB 3.5" */ - { 6240,39,2,80,0,0x1B,0x43,0xAF,0x28,"E3120"}, /* 9 3.12MB 3.5" */ + { 6240,39,2,80,0,0x1B,0x43,0xAF,0x28,"E3120" }, /* 9 3.12MB 3.5" */ { 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25" */ { 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5" */ @@ -491,8 +510,8 @@ * not contain a 64k byte boundary crossing, or data will be * corrupted/lost. */ -static char *floppy_track_buffer=0; -static int max_buffer_sectors=0; +static char *floppy_track_buffer; +static int max_buffer_sectors; static int *errors; typedef void (*done_f)(int); @@ -503,7 +522,7 @@ void (*error)(void); /* this is called to tally an error */ done_f done; /* this is called to say if the operation has * succeeded/failed */ -} *cont=NULL; +} *cont; static void floppy_ready(void); static void floppy_start(void); @@ -551,14 +570,13 @@ static unsigned char current_drive = 0; static long current_count_sectors = 0; static unsigned char sector_t; /* sector in track */ -static unsigned char in_sector_offset; /* offset within physical sector, - * expressed in units of 512 bytes */ +static unsigned char in_sector_offset; /* offset within physical sector, + * expressed in units of 512 bytes */ #ifndef fd_eject #define fd_eject(x) -EINVAL #endif - #ifdef DEBUGT static long unsigned debugtimer; #endif @@ -602,10 +620,10 @@ #define OLOGSIZE 20 static void (*lasthandler)(void) = NULL; -static unsigned long interruptjiffies=0; -static unsigned long resultjiffies=0; -static int resultsize=0; -static unsigned long lastredo=0; +static unsigned long interruptjiffies; +static unsigned long resultjiffies; +static int resultsize; +static unsigned long lastredo; static struct output_log { unsigned char data; @@ -613,7 +631,7 @@ unsigned long jiffies; } output_log[OLOGSIZE]; -static int output_log_pos=0; +static int output_log_pos; #endif #define CURRENTD -1 @@ -640,7 +658,7 @@ static int maximum(int a, int b) { - if(a > b) + if (a > b) return a; else return b; @@ -649,7 +667,7 @@ static int minimum(int a, int b) { - if(a < b) + if (a < b) return a; else return b; @@ -697,11 +715,11 @@ if (jiffies - UDRS->select_date < UDP->select_delay) DPRINT("WARNING disk change called early\n"); if (!(FDCS->dor & (0x10 << UNIT(drive))) || - (FDCS->dor & 3) != UNIT(drive) || - fdc != FDC(drive)){ + (FDCS->dor & 3) != UNIT(drive) || + fdc != FDC(drive)){ DPRINT("probing disk change on unselected drive\n"); DPRINT("drive=%d fdc=%d dor=%x\n",drive, FDC(drive), - FDCS->dor); + (unsigned int)FDCS->dor); } #endif @@ -791,7 +809,7 @@ { if (DP->select_delay) return; - fd_outb(FDCS->dor & ~(0x10<dor & ~(0x10<dor, FD_DOR); DRS->select_date = jiffies; } @@ -1034,7 +1052,7 @@ } static spinlock_t floppy_hlt_lock = SPIN_LOCK_UNLOCKED; -static int hlt_disabled=0; +static int hlt_disabled; static void floppy_disable_hlt(void) { unsigned long flags; @@ -1090,7 +1108,7 @@ f=claim_dma_lock(); fd_disable_dma(); #ifdef fd_dma_setup - if(fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length, + if (fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length, (raw_cmd->flags & FD_RAW_READ)? DMA_MODE_READ : DMA_MODE_WRITE, FDCS->address) < 0) { @@ -1120,7 +1138,7 @@ static int wait_til_ready(void) { int counter, status; - if(FDCS->reset) + if (FDCS->reset) return -1; for (counter = 0; counter < 10000; counter++) { status = fd_inb(FD_STATUS); @@ -1184,7 +1202,7 @@ else break; } - if(!initialising) { + if (!initialising) { DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n", fdc, status, i); show_floppy(); @@ -1198,7 +1216,7 @@ static int need_more_output(void) { int status; - if( (status = wait_til_ready()) < 0) + if ((status = wait_til_ready()) < 0) return -1; if ((status & (STATUS_READY|STATUS_DIR|STATUS_DMA)) == STATUS_READY) return MORE_OUTPUT; @@ -1249,7 +1267,7 @@ { /* Turn on FIFO */ output_byte(FD_CONFIGURE); - if(need_more_output() != MORE_OUTPUT) + if (need_more_output() != MORE_OUTPUT) return 0; output_byte(0); output_byte(0x10 | (no_fifo & 0x20) | (fifo_depth & 0xf)); @@ -1304,7 +1322,7 @@ /* chose the default rate table, not the one * where 1 = 2 Mbps */ output_byte(FD_DRIVESPEC); - if(need_more_output() == MORE_OUTPUT) { + if (need_more_output() == MORE_OUTPUT) { output_byte(UNIT(current_drive)); output_byte(0xc0); } @@ -1745,14 +1763,14 @@ do_print = !handler && print_unex && !initialising; inr = result(); - if(do_print) + if (do_print) print_result("unexpected interrupt", inr); if (inr == 0){ int max_sensei = 4; do { output_byte(FD_SENSEI); inr = result(); - if(do_print) + if (do_print) print_result("sensei", inr); max_sensei--; } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2 && max_sensei); @@ -2325,31 +2343,31 @@ nr_sectors = 0; CODE2SIZE; - if(ST1 & ST1_EOC) + if (ST1 & ST1_EOC) eoc = 1; else eoc = 0; - if(COMMAND & 0x80) + if (COMMAND & 0x80) heads = 2; else heads = 1; - nr_sectors = (((R_TRACK-TRACK) * heads + + nr_sectors = (((R_TRACK-TRACK) * heads + R_HEAD-HEAD) * SECT_PER_TRACK + - R_SECTOR-SECTOR + eoc) << SIZECODE >> 2; + R_SECTOR-SECTOR + eoc) << SIZECODE >> 2; #ifdef FLOPPY_SANITY_CHECK if (nr_sectors / ssize > - (in_sector_offset + current_count_sectors + ssize - 1)/ssize) { + (in_sector_offset + current_count_sectors + ssize - 1) / ssize) { DPRINT("long rw: %x instead of %lx\n", nr_sectors, current_count_sectors); printk("rs=%d s=%d\n", R_SECTOR, SECTOR); printk("rh=%d h=%d\n", R_HEAD, HEAD); printk("rt=%d t=%d\n", R_TRACK, TRACK); printk("heads=%d eoc=%d\n", heads, eoc); - printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK, - sector_t, ssize); + printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK, + sector_t, ssize); printk("in_sector_offset=%d\n", in_sector_offset); } #endif @@ -2547,22 +2565,24 @@ * does not work with MT, hence we can only transfer one head at * a time */ -static void virtualdmabug_workaround(void) { +static void virtualdmabug_workaround(void) +{ int hard_sectors, end_sector; + if(CT(COMMAND) == FD_WRITE) { COMMAND &= ~0x80; /* switch off multiple track mode */ - + hard_sectors = raw_cmd->length >> (7 + SIZECODE); end_sector = SECTOR + hard_sectors - 1; #ifdef FLOPPY_SANITY_CHECK if(end_sector > SECT_PER_TRACK) { - printk("too many sectors %d > %d\n", - end_sector, SECT_PER_TRACK); + printk("too many sectors %d > %d\n", + end_sector, SECT_PER_TRACK); return; } #endif SECT_PER_TRACK = end_sector; /* make sure SECT_PER_TRACK points - * to end of transfer */ + * to end of transfer */ } } @@ -2603,7 +2623,7 @@ TRACK = CURRENT->sector / max_sector; sector_t = CURRENT->sector % max_sector; if (_floppy->track && TRACK >= _floppy->track) { - if(CURRENT->current_nr_sectors & 1) { + if (CURRENT->current_nr_sectors & 1) { current_count_sectors = 1; return 1; } else @@ -2935,7 +2955,7 @@ static void do_fd_request(request_queue_t * q) { - if(usage_count == 0) { + if (usage_count == 0) { printk("warning: usage count=0, CURRENT=%p exiting\n", CURRENT); printk("sect=%ld cmd=%d\n", CURRENT->sector, CURRENT->cmd); return; @@ -3057,7 +3077,7 @@ raw_cmd->flags |= FD_RAW_HARDFAILURE; } else { raw_cmd->reply_count = inr; - if(raw_cmd->reply_count > MAX_REPLIES) + if (raw_cmd->reply_count > MAX_REPLIES) raw_cmd->reply_count=0; for (i=0; i< raw_cmd->reply_count; i++) raw_cmd->reply[i] = reply_buffer[i]; @@ -3382,7 +3402,7 @@ process_fd_request(); *g = current_type[drive]; } - if(!*g) + if (!*g) return -ENODEV; return 0; } @@ -3420,8 +3440,8 @@ /* convert compatibility eject ioctls into floppy eject ioctl. * We do this in order to provide a means to eject floppy disks before * installing the new fdutils package */ - if(cmd == CDROMEJECT || /* CD-ROM eject */ - cmd == 0x6470 /* SunOS floppy eject */) { + if (cmd == CDROMEJECT || /* CD-ROM eject */ + cmd == 0x6470 /* SunOS floppy eject */) { DPRINT("obsolete eject ioctl\n"); DPRINT("please use floppycontrol --eject\n"); cmd = FDEJECT; @@ -3467,7 +3487,7 @@ switch (cmd) { case FDEJECT: - if(UDRS->fd_ref != 1) + if (UDRS->fd_ref != 1) /* somebody else has this drive open */ return -EBUSY; LOCK_FDC(drive,1); @@ -3508,9 +3528,9 @@ CALL(poll_drive(1, FD_RAW_NEED_DISK)); ret = UDRS->flags; process_fd_request(); - if(ret & FD_VERIFY) + if (ret & FD_VERIFY) return -ENODEV; - if(!(ret & FD_DISK_WRITABLE)) + if (!(ret & FD_DISK_WRITABLE)) return -EROFS; return 0; case FDFMTTRK: @@ -3705,7 +3725,7 @@ INFBOUND(try, 16); tmp= (char *)fd_dma_mem_alloc(1024*try); } - if(!tmp && !floppy_track_buffer) { + if (!tmp && !floppy_track_buffer) { fallback_on_nodma_alloc(&tmp, 2048 * try); } if (!tmp && !floppy_track_buffer) { @@ -3713,7 +3733,7 @@ RETERR(ENXIO); } if (floppy_track_buffer) { - if(tmp) + if (tmp) fd_dma_mem_free((unsigned long)tmp,try*1024); } else { buffer_min = buffer_max = -1; @@ -3787,9 +3807,9 @@ int cf; if (UTESTF(FD_DISK_CHANGED) || - UTESTF(FD_VERIFY) || - test_bit(drive, &fake_change) || - NO_GEOM){ + UTESTF(FD_VERIFY) || + test_bit(drive, &fake_change) || + NO_GEOM){ lock_fdc(drive,0); cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY); if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)){ @@ -3892,13 +3912,13 @@ return FDC_UNKNOWN; } - if(!fdc_configure()) { + if (!fdc_configure()) { printk(KERN_INFO "FDC %d is an 82072\n",fdc); return FDC_82072; /* 82072 doesn't know CONFIGURE */ } output_byte(FD_PERPENDICULAR); - if(need_more_output() == MORE_OUTPUT) { + if (need_more_output() == MORE_OUTPUT) { output_byte(0); } else { printk(KERN_INFO "FDC %d is an 82072A\n", fdc); @@ -4037,7 +4057,8 @@ { "unexpected_interrupts", 0, &print_unex, 1, 0 }, { "no_unexpected_interrupts", 0, &print_unex, 0, 0 }, - { "L40SX", 0, &print_unex, 0, 0 } }; + { "L40SX", 0, &print_unex, 0, 0 } +}; static int __init floppy_setup(char *str) { @@ -4053,11 +4074,11 @@ param = ints[1]; else param = config_params[i].def_param; - if(config_params[i].fn) + if (config_params[i].fn) config_params[i]. fn(ints,param, config_params[i].param2); - if(config_params[i].var) { + if (config_params[i].var) { DPRINT("%s=%d\n", str, param); *config_params[i].var = param; } @@ -4086,7 +4107,7 @@ int i,unit,drive; - raw_cmd = 0; + raw_cmd = NULL; devfs_handle = devfs_mk_dir (NULL, "floppy", 0, NULL); if (devfs_register_blkdev(MAJOR_NR,"fd",&floppy_fops)) { @@ -4174,7 +4195,7 @@ FDCS->address = -1; continue; } - if(can_use_virtual_dma == 2 && FDCS->version < FDC_82072A) + if (can_use_virtual_dma == 2 && FDCS->version < FDC_82072A) can_use_virtual_dma = 0; have_no_fdc = 0; @@ -4192,13 +4213,13 @@ if (have_no_fdc) { DPRINT("no floppy controllers found\n"); - floppy_tq.routine = (void *)(void *) empty; + floppy_tq.routine = (void *)(void *) empty; mark_bh(IMMEDIATE_BH); schedule(); - if (usage_count) - floppy_release_irq_and_dma(); + if (usage_count) + floppy_release_irq_and_dma(); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); - devfs_unregister_blkdev(MAJOR_NR,"fd"); + devfs_unregister_blkdev(MAJOR_NR,"fd"); } for (drive = 0; drive < N_DRIVE; drive++) { @@ -4324,7 +4345,7 @@ if (floppy_track_buffer && max_buffer_sectors) { tmpsize = max_buffer_sectors*1024; tmpaddr = (unsigned long)floppy_track_buffer; - floppy_track_buffer = 0; + floppy_track_buffer = NULL; max_buffer_sectors = 0; buffer_min = buffer_max = -1; fd_dma_mem_free(tmpaddr, tmpsize); @@ -4357,7 +4378,7 @@ #ifdef MODULE -char *floppy=NULL; +char *floppy; static void __init parse_floppy_cfg_string(char *cfg) { @@ -4365,11 +4386,11 @@ while(*cfg) { for(ptr = cfg;*cfg && *cfg != ' ' && *cfg != '\t'; cfg++); - if(*cfg) { + if (*cfg) { *cfg = '\0'; cfg++; } - if(*ptr) + if (*ptr) floppy_setup(ptr); } } @@ -4378,7 +4399,7 @@ { printk(KERN_INFO "inserting floppy driver for " UTS_RELEASE "\n"); - if(floppy) + if (floppy) parse_floppy_cfg_string(floppy); return floppy_init(); } @@ -4411,7 +4432,7 @@ void floppy_eject(void) { int dummy; - if(have_no_fdc) + if (have_no_fdc) return; if(floppy_grab_irq_and_dma()==0) { diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/block/loop.c linux/drivers/block/loop.c --- v2.3.99-pre8/linux/drivers/block/loop.c Thu May 11 15:30:06 2000 +++ linux/drivers/block/loop.c Mon May 15 14:54:32 2000 @@ -289,7 +289,8 @@ if (lo->lo_flags & LO_FLAGS_READ_ONLY) goto error_out; } else if (current_request->cmd != READ) { - printk(KERN_ERR "unknown loop device command (%d)?!?", current_request->cmd); + printk(KERN_ERR "unknown loop device command (%d)?!?", + current_request->cmd); goto error_out; } @@ -423,8 +424,28 @@ /* Backed by a block device - don't need to hold onto a file structure */ lo->lo_backing_file = NULL; + + if (error) + goto out_putf; } else if (S_ISREG(inode->i_mode)) { struct address_space_operations *aops; + + aops = inode->i_mapping->a_ops; + /* + * If we can't read - sorry. If we only can't write - well, + * it's going to be read-only. + */ + error = -EINVAL; + if (!aops->readpage) + goto out_putf; + + if (!aops->prepare_write || !aops->commit_write) + lo->lo_flags |= LO_FLAGS_READ_ONLY; + + error = get_write_access(inode); + if (error) + goto out_putf; + /* Backed by a regular file - we need to hold onto a file structure for this file. Friggin' NFS can't live without it on write and for reading we use do_generic_file_read(), @@ -437,35 +458,23 @@ error = -ENFILE; lo->lo_backing_file = get_empty_filp(); - if (lo->lo_backing_file) { - lo->lo_backing_file->f_mode = file->f_mode; - lo->lo_backing_file->f_pos = file->f_pos; - lo->lo_backing_file->f_flags = file->f_flags; - lo->lo_backing_file->f_owner = file->f_owner; - lo->lo_backing_file->f_dentry = file->f_dentry; - lo->lo_backing_file->f_vfsmnt = file->f_vfsmnt; - lo->lo_backing_file->f_op = file->f_op; - lo->lo_backing_file->private_data = file->private_data; - file_moveto(lo->lo_backing_file, file); - - error = get_write_access(inode); - if (error) { - put_filp(lo->lo_backing_file); - lo->lo_backing_file = NULL; - } - } - aops = inode->i_mapping->a_ops; - /* - * If we can't read - sorry. If we only can't write - well, - * it's going to be read-only. - */ - if (!aops->readpage) - error = -EINVAL; - else if (!aops->prepare_write || !aops->commit_write) - lo->lo_flags |= LO_FLAGS_READ_ONLY; + if (lo->lo_backing_file == NULL) { + put_write_access(inode); + goto out_putf; + } + + lo->lo_backing_file->f_mode = file->f_mode; + lo->lo_backing_file->f_pos = file->f_pos; + lo->lo_backing_file->f_flags = file->f_flags; + lo->lo_backing_file->f_owner = file->f_owner; + lo->lo_backing_file->f_dentry = file->f_dentry; + lo->lo_backing_file->f_vfsmnt = mntget(file->f_vfsmnt); + lo->lo_backing_file->f_op = file->f_op; + lo->lo_backing_file->private_data = file->private_data; + file_moveto(lo->lo_backing_file, file); + + error = 0; } - if (error) - goto out_putf; if (IS_RDONLY (inode) || is_read_only(lo->lo_device)) lo->lo_flags |= LO_FLAGS_READ_ONLY; @@ -477,9 +486,9 @@ lo->ioctl = NULL; figure_loop_size(lo); -out_putf: + out_putf: fput(file); -out: + out: if (error) MOD_DEC_USE_COUNT; return error; @@ -530,6 +539,7 @@ lo->lo_dentry = NULL; if (lo->lo_backing_file != NULL) { + put_write_access(lo->lo_backing_file->f_dentry->d_inode); fput(lo->lo_backing_file); lo->lo_backing_file = NULL; } else { diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/block/xor.c linux/drivers/block/xor.c --- v2.3.99-pre8/linux/drivers/block/xor.c Fri May 12 14:18:55 2000 +++ linux/drivers/block/xor.c Mon May 15 12:10:26 2000 @@ -15,6 +15,7 @@ * (for example /usr/src/linux/COPYING); if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #define BH_TRACE 0 #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v2.3.99-pre8/linux/drivers/char/Config.in Thu May 11 15:30:06 2000 +++ linux/drivers/char/Config.in Mon May 22 09:50:53 2000 @@ -50,6 +50,10 @@ bool ' Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS fi tristate ' Specialix SX (and SI) card support' CONFIG_SX + tristate ' Specialix RIO system support' CONFIG_RIO + if [ "$CONFIG_RIO" != "n" ]; then + bool ' Support really old RIO/PCI cards' CONFIG_RIO_OLDPCI + fi bool ' Stallion multiport serial support' CONFIG_STALDRV if [ "$CONFIG_STALDRV" = "y" ]; then tristate ' Stallion EasyIO or EC8/32 support' CONFIG_STALLION @@ -201,7 +205,7 @@ fi comment 'Video Adapters' if [ "$CONFIG_I2C_ALGOBIT" = "y" -o "$CONFIG_I2C_ALGOBIT" = "m" ]; then - dep_tristate ' BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C_ALGOBIT + dep_tristate ' BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C_ALGOBIT $CONFIG_SOUND fi dep_tristate ' Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV if [ "$CONFIG_ALL_PPC" = "y" ]; then diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v2.3.99-pre8/linux/drivers/char/Makefile Thu May 11 15:30:06 2000 +++ linux/drivers/char/Makefile Sat May 20 12:07:56 2000 @@ -136,41 +136,38 @@ obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o obj-$(CONFIG_SX) += sx.o +# If either SX or RIO is in the kernel, generic_serial goes in the +# kernel, and the module is no longer required. The "in kernel" case +# is last to be able to override the module case.... This is an +# example of the new "makefile automatically figures out the +# dependencies".... -- REW -# If either is in the kernel, generic_serial goes in the kernel, and -# the module is no longer required. The "in kernel" case is last to be -# able to override the module case.... This is an example of the new -# "makefile automatically figures out the dependencies".... -- REW +GS=n +ifeq ($(CONFIG_RIO),m) + M_OBJS += generic_serial.o + MOD_SUB_DIRS += rio + GS = m +endif -GS = n ifeq ($(CONFIG_SX),m) GS = m + M_OBJS += sx.o endif -ifeq ($(CONFIG_RIO),m) - GS = m -endif -ifeq ($(CONFIG_SX),y) - GS = y -endif -ifeq ($(CONFIG_RIO),y) - GS = y -endif -obj-$(GS) += generic_serial.o - - - ifeq ($(CONFIG_RIO),y) -obj-y += rio/rio.o generic_serial.o -SUB_DIRS += rio -MOD_SUB_DIRS += rio -else - ifeq ($(CONFIG_RIO),m) - obj-m += generic_serial.o + L_OBJS += rio/rio.o generic_serial.o + SUB_DIRS += rio MOD_SUB_DIRS += rio - endif + GS = y endif +ifeq ($(CONFIG_SX),y) + L_OBJS += sx.o + GS = y +endif + +obj-$(GS) += generic_serial.o + obj-$(CONFIG_ATIXL_BUSMOUSE) += atixlmouse.o obj-$(CONFIG_LOGIBUSMOUSE) += logibusmouse.o obj-$(CONFIG_PRINTER) += lp.o @@ -205,7 +202,7 @@ obj-$(CONFIG_MIXCOMWD) += mixcomwd.o obj-$(CONFIG_AMIGAMOUSE) += amigamouse.o obj-$(CONFIG_ATARIMOUSE) += atarimouse.o -obj-$(CONFIG_ADBMOUSE) += adbmouse.o busmouse.o +obj-$(CONFIG_ADBMOUSE) += adbmouse.o obj-$(CONFIG_PC110_PAD) += pc110pad.o obj-$(CONFIG_WDT) += wdt.o obj-$(CONFIG_WDTPCI) += wdt_pci.o @@ -232,7 +229,8 @@ endif endif -obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tda8425.o tda985x.o tea6300.o +obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o \ + tda7432.o tda8425.o tda985x.o tda9875.o tea6300.o tea6420.o ifeq ($(CONFIG_VIDEO_BT848),y) L_TUNERS=y else diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/bttv.c linux/drivers/char/bttv.c --- v2.3.99-pre8/linux/drivers/char/bttv.c Thu May 11 15:30:06 2000 +++ linux/drivers/char/bttv.c Mon May 22 09:50:53 2000 @@ -43,19 +43,13 @@ #include #include #include - -#ifdef LOCK_I2C_BUS -# error INSTALL ERROR -# error gcc uses the old, obsolete i2c.h include file. Please install the \ - new i2c stack. Please install it by patching the kernel, otherwise \ - gcc will not find the new header files. -#endif +#include #include "bttv.h" #include "tuner.h" -#define DEBUG(x) /* Debug driver */ -#define IDEBUG(x) /* Debug interrupt handler */ +#define DEBUG(x) /* Debug driver */ +#define IDEBUG(x) /* Debug interrupt handler */ #define MIN(a,b) (((a)>(b))?(b):(a)) #define MAX(a,b) (((a)>(b))?(a):(b)) @@ -100,7 +94,7 @@ static unsigned long remap[BTTV_MAX]; static unsigned int radio[BTTV_MAX]; static unsigned int card[BTTV_MAX] = { 0, 0, 0, 0 }; -static unsigned int pll[BTTV_MAX] = { 0, 0, 0, 0}; +static unsigned int pll[BTTV_MAX] = { -1, -1, -1, -1}; static unsigned int fieldnr = 0; static unsigned int verbose = 1; static unsigned int debug = 0; @@ -473,7 +467,7 @@ NULL }; -static int init_bttv_i2c(struct bttv *btv) +static int __init init_bttv_i2c(struct bttv *btv) { /* i2c bit_adapter */ memcpy(&btv->i2c_adap, &i2c_adap_template, sizeof(struct i2c_adapter)); @@ -495,7 +489,7 @@ } /* read I2C */ -static int I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) +static int __init I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) { unsigned char buffer = 0; @@ -520,7 +514,7 @@ } /* write I2C */ -static int I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, +static int __init I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, unsigned char b2, int both) { unsigned char buffer[2]; @@ -537,7 +531,7 @@ } /* read EEPROM */ -static void readee(struct bttv *btv, unsigned char *eedata, int addr) +static void __init readee(struct bttv *btv, unsigned char *eedata, int addr) { int i; @@ -564,7 +558,7 @@ int id; char *name; } -hauppauge_tuner[] = +hauppauge_tuner[] __initdata = { { TUNER_ABSENT, "" }, { TUNER_ABSENT, "External" }, @@ -612,8 +606,7 @@ { TUNER_ABSENT, "Temic 4046FM5" }, }; -static void -hauppauge_eeprom(struct bttv *btv) +static void __init hauppauge_eeprom(struct bttv *btv) { if (eeprom_data[9] < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) { @@ -622,10 +615,11 @@ printk("bttv%d: Hauppauge eeprom: tuner=%s (%d)\n",btv->nr, hauppauge_tuner[eeprom_data[9]].name,btv->tuner_type); } + + return; } -static void -hauppauge_boot_msp34xx(struct bttv *btv) +static void __init hauppauge_boot_msp34xx(struct bttv *btv) { int i; @@ -661,7 +655,7 @@ /* This is basically the same procedure as * used by Alessandro Rubini in his pxc200 * driver, but using BTTV functions */ -static void init_PXC200(struct bttv *btv) +static void __init init_PXC200(struct bttv *btv) { static const int vals[] = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, @@ -711,21 +705,25 @@ unsigned id; int cardnr; char *name; -} cards[] = { +} cards[] __initdata = { { 0x00011002, BTTV_HAUPPAUGE878, "ATI TV Wonder" }, - { 0x00031461, BTTV_AVERMEDIA98, "AVerMedia TVPhone98" }, + { 0x00011461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, + { 0x00031461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, + { 0x00041461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, { 0x10b42636, BTTV_HAUPPAUGE878, "STB ???" }, { 0x1118153b, BTTV_TERRATVALUE, "Terratec TV Value" }, + { 0x1200bd11, BTTV_PINNACLERAVE, "Pinnacle PCTV Rave" }, { 0x13eb0070, BTTV_HAUPPAUGE878, "Hauppauge WinTV" }, { 0x14610002, BTTV_AVERMEDIA98, "Avermedia TVCapture 98" }, { 0x18501851, BTTV_CHRONOS_VS2, "Chronos Video Shuttle II" }, { 0x18521852, BTTV_TYPHOON_TVIEW, "Typhoon TView TV/FM Tuner" }, + { 0x263610b4, BTTV_STB2, "STB TV PCI FM, P/N 6000704" }, { 0x3000144f, BTTV_MAGICTVIEW063, "TView 99 (CPH063)" }, { 0x300014ff, BTTV_MAGICTVIEW061, "TView 99 (CPH061)" }, { 0x3002144f, BTTV_MAGICTVIEW061, "Askey Magic TView" }, { 0x300214ff, BTTV_PHOEBE_TVMAS, "Phoebe TV Master" }, + { 0x402010fc, 0 /* no tvcards entry yet */, "I-O Data Co. GV-BCV3/PCI" }, { 0x6606217d, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, - { 0x1200bd11, BTTV_PINNACLERAVE, "Pinnacle PCTV Rave" }, { 0, -1, NULL } }; @@ -747,6 +745,13 @@ int tda9840:1; int tda985x:1; int tea63xx:1; + int tea64xx:1; + int tda7432:1; + int tda9875:1; + + /* other settings */ + int pll; + int tuner_type; }; static struct tvcard tvcards[] = @@ -754,149 +759,161 @@ /* 0x00 */ { " *** UNKNOWN *** ", 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "MIRO PCTV", 4, 1, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Hauppauge old", 4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,0,1,0 }, + 1,1,0,1,0,0,0,1, PLL_NONE, -1 }, { "STB", 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1},0, - 0,1,1,1,1 }, + 0,1,1,1,1,0,0,1, PLL_NONE, -1 }, { "Intel", - 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,1,1,0 }, + 3, 1, 0, -1, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Diamond DTV2000", 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "AVerMedia TVPhone", 3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 4,11,11, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "MATRIX-Vision MV-Delta", 5, 1, -1, 3, 0, { 2, 3, 1, 0, 0},{0 }, 0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, /* 0x08 */ { "Fly Video II", 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1}, { 0, 0xc00, 0x800, 0x400, 0xc00, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "TurboTV", 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Hauppauge new (bt878)", 4, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,0,1,0 }, + 1,1,0,1,0,0,0,1, PLL_28, -1 }, { "MIRO PCTV pro", 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "ADS Technologies Channel Surfer TV", 3, 1, 2, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "AVerMedia TVCapture 98", 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_28, -1 }, { "Aimslab VHX", 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Zoltrix TV-Max", 3, 1, 0, 2,15, { 2, 3, 1, 1}, {0 , 0, 1 , 0, 10},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, /* 0x10 */ { "Pixelview PlayTV (bt878)", - 3, 1, 0, 2, 0x01e000, { 2, 0, 1, 1}, + 3, 1, 0, 2, 0x01fe00, { 2, 0, 1, 1}, { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 },0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_28, -1 }, { "Leadtek WinView 601", 3, 1, 0, 2, 0x8300f8, { 2, 3, 1, 1,0}, { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "AVEC Intercapture", 3, 2, 0, 2, 0, {2, 3, 1, 1}, {1, 0, 0, 0, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "LifeView FlyKit w/o Tuner", 3, 1, -1, -1, 0x8dff00, { 2, 3, 1, 1}, { 0 },0, - 0,0,0,0,0 }, + 0,0,0,0,0,0,0,1, PLL_NONE, -1 }, { "CEI Raffles Card", 3, 3, 0, 2, 0, {2, 3, 1, 1}, {0, 0, 0, 0 ,0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Lucky Star Image World ConferenceTV", - 3, 1, 0, 2, 16777215, { 2, 3, 1, 1}, { 131072, 1, 1638400, 3, 4},0, - 1,1,1,1,0 }, + 3, 1, 0, 2, 0x00fffe07, { 2, 3, 1, 1}, { 131072, 1, 1638400, 3, 4},0, + 1,1,1,1,0,0,0,1, PLL_28, TUNER_PHILIPS_PAL_I }, { "Phoebe Tv Master + FM", 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1},{0, 1, 0x800, 0x400, 0xc00, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Modular Technology MM205 PCTV, bt878", 2, 1, 0, -1, 7, { 2, 3 }, { 0, 0, 0, 0, 0 },0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, /* 0x18 */ { "Askey/Typhoon/Anubis Magic TView CPH051/061 (bt878)", 3, 1, 0, 2, 0xe00, { 2, 3, 1, 1}, {0x400, 0x400, 0x400, 0x400, 0},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_28, -1 }, { "Terratec/Vobis TV-Boostar", 3, 1, 0, 2, 16777215 , { 2, 3, 1, 1}, { 131072, 1, 1638400, 3,4},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Newer Hauppauge WinCam (bt878)", 4, 1, 0, 3, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "MAXI TV Video PCI2", 3, 1, 0, 2, 0xffff, { 2, 3, 1, 1}, { 0, 1, 2, 3, 0xc00},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, TUNER_PHILIPS_SECAM }, { "Terratec TerraTV+", 3, 1, 0, 2, 0x70000, { 2, 3, 1, 1}, { 0x20000, 0x30000, 0x00000, 0x10000, 0x40000},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Imagenation PXC200", 5, 1, -1, 4, 0, { 2, 3, 1, 0, 0}, { 0 }, 0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "FlyVideo 98", 3, 1, 0, 2, 0x8dff00, {2, 3, 1, 1}, { 0, 0x8dff00, 0x8df700, 0x8de700, 0x8dff00, 0 },0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "iProTV", 3, 1, 0, 2, 1, { 2, 3, 1, 1}, { 1, 0, 0, 0, 0 },0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, /* 0x20 */ { "Intel Create and Share PCI", 4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 4, 4, 4, 4},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Terratec TerraTValue", - 3, 1, 0, 2, 0xf00, { 2, 3, 1, 1}, { 0x500, 0, 0x300, 0x900, 0x900},0, - 1,1,1,1,0 }, + 3, 1, 0, 2, 0xffff00, { 2, 3, 1, 1}, + { 0x500, 0, 0x300, 0x900, 0x900},0, + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, { "Leadtek WinFast 2000", 3, 1, 0, 2, 0xfff000, { 2, 3, 1, 1,0}, { 0x621000,0x620100,0x621100,0x620000,0xE210000,0x620000},0, - 1,1,1,1,1 }, + 1,1,1,1,1,0,0,1, PLL_28, -1 }, { "Chronos Video Shuttle II", 3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0, 0x1000, 0x1000, 0x0800},0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_28, -1 }, { "Typhoon TView TV/FM Tuner", 3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0x800, 0, 0, 0x1800, 0 },0, - 1,1,1,1,0 }, + 1,1,1,1,0,0,0,1, PLL_28, -1 }, { "PixelView PlayTV pro", 3, 1, 0, 2, 0xff, { 2, 3, 1, 1 }, - { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, 0 }, + { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, 0, + 0,0,0,0,0,0,0,1, PLL_28, -1 }, { "TView99 CPH063", - 3, 1, 0, 2, 0x551e00, { 2, 0, 1, 1}, - { 0x551400, 0x551200, 0, 0, 0x551200 }, 0,1,1,1,1,0 }, + 3, 1, 0, 2, 0x551e00, { 2, 3, 1, 1}, + { 0x551400, 0x551200, 0, 0, 0, 0x551200 }, 0, + 1,1,1,1,0,0,0,1, PLL_28, -1 }, { "Pinnacle PCTV Rave", 3, 1, 0, 2, 0x03000F, { 2, 3, 1, 1}, { 2, 0, 0, 0, 1},0, - 1,1,1,1,0 }, - + 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, + + /* 0x28 */ + { "STB2", + 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1},0, + 0,1,1,1,0,1,1,1, PLL_NONE, -1 }, + { "AVerMedia TVPhone 98", + 3, 4, 0, 2, 4, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0, + 1,1,1,1,0,0,0,1, PLL_28, 5 }, + { "ProVideo PV951", /* pic16c54 */ + 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0},0, + 0,0,0,0,0,0,0,0, PLL_28, 1 }, }; #define TVCARDS (sizeof(tvcards)/sizeof(struct tvcard)) -static void -dump_eeprom(struct bttv *btv,int addr) +static void __init dump_eeprom(struct bttv *btv,int addr) { int i; @@ -913,8 +930,7 @@ } } -static int -idcard_eeprom(struct bttv *btv) +static int __init idcard_eeprom(struct bttv *btv) { unsigned id; int i,n; @@ -1477,6 +1493,10 @@ unsigned char lmask, rmask, *p; int W, l, r; int i; + + if (debug) + printk("bttv clip: %dx%d+%d+%d\n",w,h,x,y); + /* bitmap is fixed width, 128 bytes (1024 pixels represented) */ if (x<0) { @@ -1497,10 +1517,10 @@ w=1024-x; l=x>>3; - r=(x+w)>>3; + r=(x+w-1)>>3; W=r-l-1; lmask=lmaskt[x&7]; - rmask=rmaskt[(x+w)&7]; + rmask=rmaskt[(x+w-1)&7]; p=clipmap+128*y+l; if (W>0) @@ -1716,8 +1736,7 @@ struct tvnorm *tvn; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&btv->s_lock, flags); tvn=&tvnorms[btv->win.norm]; @@ -1771,7 +1790,7 @@ btwrite(format, BT848_COLOR_FMT); btwrite(bswap | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); - restore_flags(flags); + spin_unlock_irqrestore(&btv->s_lock, flags); } @@ -1835,6 +1854,7 @@ { unsigned int *ro, *re; unsigned int *vbuf; + unsigned long flags; if(btv->fbuffer==NULL) { @@ -1870,7 +1890,7 @@ if (debug) printk("bttv%d: cap vgrab: queue %d (%d:%dx%d)\n", btv->nr,mp->frame,mp->format,mp->width,mp->height); - cli(); + spin_lock_irqsave(&btv->s_lock, flags); btv->gbuf[mp->frame].stat = GBUFFER_GRABBING; btv->gbuf[mp->frame].fmt = palette2fmt[mp->format]; btv->gbuf[mp->frame].width = mp->width; @@ -1885,12 +1905,13 @@ #endif if (btv->gq_in == btv->gq_out) { + btv->gq_start = 1; btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ); } btv->gqueue[btv->gq_in++] = mp->frame; btv->gq_in = btv->gq_in % MAX_GBUFFERS; - sti(); + spin_unlock_irqrestore(&btv->s_lock, flags); btor(3, BT848_CAP_CTL); btor(3, BT848_GPIO_DMA_CTL); return 0; @@ -1911,23 +1932,25 @@ todo=count; while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) { + unsigned long flags; + if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, q)) return -EFAULT; todo-=q; buf+=q; - cli(); + spin_lock_irqsave(&btv->s_lock, flags); if (todo && q==VBIBUF_SIZE-btv->vbip) { if(nonblock) { - sti(); + spin_unlock_irqrestore(&btv->s_lock, flags); if(count==todo) return -EWOULDBLOCK; return count-todo; } + spin_unlock_irqrestore(&btv->s_lock, flags); interruptible_sleep_on(&btv->vbiq); - sti(); if(signal_pending(current)) { if(todo==count) @@ -1935,7 +1958,8 @@ else return count-todo; } - } + } else + spin_unlock_irqrestore(&btv->s_lock, flags); } if (todo) { @@ -1958,7 +1982,7 @@ { if (verbose) printk("bttv%d: resetting chip\n",btv->nr); - btwrite(0xfffffUL, BT848_INT_STAT); + btwrite(~0x0UL, BT848_INT_STAT); btand(~15, BT848_GPIO_DMA_CTL); btwrite(0, BT848_SRESET); btwrite(virt_to_bus(btv->risc_jmp+2), @@ -1984,6 +2008,8 @@ int i,ret; ret = -EBUSY; + + MOD_INC_USE_COUNT; down(&btv->lock); if (btv->user) goto out_unlock; @@ -2005,11 +2031,11 @@ set_pll(btv); btv->user++; up(&btv->lock); - MOD_INC_USE_COUNT; return 0; out_unlock: up(&btv->lock); + MOD_DEC_USE_COUNT; return ret; } @@ -2033,14 +2059,15 @@ btread(BT848_I2C); /* This fixes the PCI posting delay */ - /* - * This is sucky but right now I can't find a good way to - * be sure its safe to free the buffer. We wait 5-6 fields - * which is more than sufficient to be sure. - */ - - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(HZ/10); /* Wait 1/10th of a second */ + if (-1 != btv->gq_grab) { + /* + * This is sucky but right now I can't find a good way to + * be sure its safe to free the buffer. We wait 5-6 fields + * which is more than sufficient to be sure. + */ + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ/10); /* Wait 1/10th of a second */ + } /* * We have allowed it to drain. @@ -2726,6 +2753,8 @@ todo=count; while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) { + unsigned long flags; + if (btv->needs_restart) { down(&btv->lock); bt848_restart(btv); @@ -2736,18 +2765,18 @@ todo-=q; buf+=q; - cli(); + spin_lock_irqsave(&btv->s_lock, flags); if (todo && q==VBIBUF_SIZE-btv->vbip) { if(nonblock) { - sti(); + spin_unlock_irqrestore(&btv->s_lock, flags); if(count==todo) return -EWOULDBLOCK; return count-todo; } + spin_unlock_irqrestore(&btv->s_lock, flags); interruptible_sleep_on(&btv->vbiq); - sti(); if(signal_pending(current)) { if(todo==count) @@ -2755,7 +2784,8 @@ else return count-todo; } - } + } else + spin_unlock_irqrestore(&btv->s_lock, flags); } if (todo) { @@ -2784,6 +2814,8 @@ { struct bttv *btv=(struct bttv *)(dev-2); + MOD_INC_USE_COUNT; + down(&btv->lock); if (btv->needs_restart) bt848_restart(btv); @@ -2792,7 +2824,6 @@ bt848_set_risc_jmps(btv,-1); up(&btv->lock); - MOD_INC_USE_COUNT; return 0; } @@ -2864,6 +2895,7 @@ struct bttv *btv = (struct bttv *)(dev-1); unsigned long v; + MOD_INC_USE_COUNT; down(&btv->lock); if (btv->user) goto busy_unlock; @@ -2876,11 +2908,11 @@ bt848_muxsel(btv,0); up(&btv->lock); - MOD_INC_USE_COUNT; return 0; busy_unlock: up(&btv->lock); + MOD_DEC_USE_COUNT; return -EBUSY; } @@ -2986,7 +3018,7 @@ #define TRITON_PEER_CONCURRENCY (1<<3) -static void handle_chipset(void) +static void __init handle_chipset(void) { struct pci_dev *dev = NULL; @@ -3018,7 +3050,7 @@ /* can tda9855.c handle this too maybe? */ -static void init_tda9840(struct bttv *btv) +static void __init init_tda9840(struct bttv *btv) { /* Horrible Hack */ I2CWrite(btv, I2C_TDA9840, TDA9840_SW, 0x2a, 1); /* sound mode switching */ @@ -3034,17 +3066,16 @@ /* Figure out card and tuner type */ -static void idcard(int i) +static void __init idcard(struct bttv *btv) { - struct bttv *btv = &bttvs[i]; int type,eeprom = 0; btwrite(0, BT848_GPIO_OUT_EN); - DEBUG(printk(KERN_DEBUG "bttv%d: GPIO: 0x%08x\n", i, btread(BT848_GPIO_DATA))); + DEBUG(printk(KERN_DEBUG "bttv%d: GPIO: 0x%08x\n", btv->nr, btread(BT848_GPIO_DATA))); /* Default the card to the user-selected one. */ - if (card[i] >= 0 && card[i] < TVCARDS) - btv->type=card[i]; + if (card[btv->nr] >= 0 && card[btv->nr] < TVCARDS) + btv->type=card[btv->nr]; /* If we were asked to auto-detect, then do so! */ if (btv->type == BTTV_UNKNOWN) { @@ -3063,7 +3094,7 @@ btv->type=BTTV_HAUPPAUGE; } - /* STB cards have a eeprom @ 0xae */ + /* STB cards have a eeprom @ 0xae (old bt848) */ } else if (I2CRead(btv, I2C_STBEE, "eeprom")>=0) { btv->type=BTTV_STB; } @@ -3078,20 +3109,20 @@ } /* print which board we have found */ - printk(KERN_INFO "bttv%d: model: ",btv->nr); - sprintf(btv->video_dev.name,"BT%d%s(%.22s)", btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "", tvcards[btv->type].name); - printk("%s\n",btv->video_dev.name); + printk(KERN_INFO "bttv%d: model: %s\n",btv->nr,btv->video_dev.name); + /* board specific initialisations */ if (btv->type == BTTV_MIRO || btv->type == BTTV_MIROPRO) { /* auto detect tuner for MIRO cards */ btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7; } if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878) { + /* pick up some config infos from the eeprom */ if (0xa0 != eeprom) { eeprom = 0xa0; readee(btv,eeprom_data,0xa0); @@ -3099,32 +3130,42 @@ hauppauge_eeprom(btv); hauppauge_boot_msp34xx(btv); } - if (btv->type == BTTV_MAXI) { - /* PHILIPS FI1216MK2 tuner (PAL/SECAM) */ - btv->tuner_type=TUNER_PHILIPS_SECAM; - } - if (btv->type == BTTV_PXC200) init_PXC200(btv); - - if (btv->type == BTTV_CONFERENCETV) - btv->tuner_type = 1; - - if (btv->type == BTTV_HAUPPAUGE878 || - btv->type == BTTV_CONFERENCETV || - btv->type == BTTV_PIXVIEWPLAYTV || - btv->type == BTTV_AVERMEDIA98 || - btv->type == BTTV_MAGICTVIEW061 || - btv->type == BTTV_MAGICTVIEW063 || - btv->type == BTTV_CHRONOS_VS2 || - btv->type == BTTV_TYPHOON_TVIEW || - btv->type == BTTV_PXELVWPLTVPRO || - btv->type == BTTV_WINFAST2000) { - btv->pll.pll_ifreq=28636363; - btv->pll.pll_crystal=BT848_IFORM_XT0; - } - if (btv->tuner_type != -1) + + /* pll configuration */ + if (!(btv->id==848 && btv->revision==0x11)) { + /* defaults from card list */ + if (PLL_28 == tvcards[btv->type].pll) { + btv->pll.pll_ifreq=28636363; + btv->pll.pll_crystal=BT848_IFORM_XT0; + } + /* insmod options can override */ + switch (pll[btv->nr]) { + case 0: /* none */ + btv->pll.pll_crystal = 0; + btv->pll.pll_ifreq = 0; + btv->pll.pll_ofreq = 0; + break; + case 1: /* 28 MHz */ + btv->pll.pll_ifreq = 28636363; + btv->pll.pll_ofreq = 0; + btv->pll.pll_crystal=BT848_IFORM_XT0; + break; + case 2: /* 35 MHz */ + btv->pll.pll_ifreq = 35468950; + btv->pll.pll_ofreq = 0; + btv->pll.pll_crystal=BT848_IFORM_XT1; + break; + } + } + + + /* tuner configuration */ + if (-1 != tvcards[btv->type].tuner_type) + btv->tuner_type = tvcards[btv->type].tuner_type; + if (btv->tuner_type != -1) call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); /* try to detect audio/fader chips */ @@ -3154,12 +3195,28 @@ request_module("tda985x"); } - if (tvcards[btv->type].tea63xx /* && - I2CRead(btv, I2C_TEA6300, "TEA63xx") >= 0 */) { + if (tvcards[btv->type].tda9875 && + I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) { + if (autoload) + request_module("tda9875"); + } + + if (tvcards[btv->type].tda7432 && + I2CRead(btv, I2C_TDA7432, "TDA7432") >=0) { + if (autoload) + request_module("tda7432"); + } + + if (tvcards[btv->type].tea63xx) { if (autoload) request_module("tea6300"); } + if (tvcards[btv->type].tea64xx) { + if (autoload) + request_module("tea6420"); + } + if (tvcards[btv->type].tuner != -1) { if (autoload) request_module("tuner"); @@ -3171,6 +3228,10 @@ static void bt848_set_risc_jmps(struct bttv *btv, int flags) { + unsigned long irq_flags; + + spin_lock_irqsave(&btv->s_lock, irq_flags); + if (-1 == flags) { /* defaults */ flags = 0; @@ -3242,7 +3303,11 @@ btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_jmp+12)); } - btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP); + if (btv->gq_start) { + btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ); + } else { + btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP); + } btv->risc_jmp[13]=cpu_to_le32(virt_to_bus(btv->risc_jmp)); /* enable cpaturing and DMA */ @@ -3253,18 +3318,17 @@ bt848_dma(btv, 3); else bt848_dma(btv, 0); + + spin_unlock_irqrestore(&btv->s_lock, irq_flags); } -static int -init_video_dev(struct bttv *btv) +static int __init init_video_dev(struct bttv *btv) { - int num = btv - bttvs; - memcpy(&btv->video_dev,&bttv_template, sizeof(bttv_template)); memcpy(&btv->vbi_dev,&vbi_template, sizeof(vbi_template)); memcpy(&btv->radio_dev,&radio_template,sizeof(radio_template)); - idcard(num); + idcard(btv); if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0) return -1; @@ -3273,7 +3337,7 @@ video_unregister_device(&btv->video_dev); return -1; } - if (radio[num]) + if (radio[btv->nr]) { if(video_register_device(&btv->radio_dev, VFL_TYPE_RADIO)<0) { @@ -3285,9 +3349,8 @@ return 1; } -static int init_bt848(int i) +static int __init init_bt848(struct bttv *btv) { - struct bttv *btv = &bttvs[i]; int j; btv->user=0; @@ -3297,14 +3360,14 @@ * might help to make a new card work */ if (verbose >= 2) printk("bttv%d: gpio: out_enable=0x%x, data=0x%x, in=0x%x\n", - i, + btv->nr, btread(BT848_GPIO_OUT_EN), btread(BT848_GPIO_DATA), btread(BT848_GPIO_REG_INP)); /* reset the bt848 */ btwrite(0, BT848_SRESET); - DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%lx\n",i,(unsigned long) btv->bt848_mem)); + DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%lx\n", btv->nr, (unsigned long) btv->bt848_mem)); /* not registered yet */ btv->video_dev.minor = -1; @@ -3412,7 +3475,7 @@ btwrite(0x00, BT848_O_SCLOOP); /* clear interrupt status */ - btwrite(0xfffffUL, BT848_INT_STAT); + btwrite(~0x0UL, BT848_INT_STAT); /* set interrupt mask */ btwrite(btv->triton1| @@ -3452,7 +3515,6 @@ astat=stat&btread(BT848_INT_MASK); if (!astat) return; - btwrite(astat,BT848_INT_STAT); IDEBUG(printk ("bttv%d: astat=%08x\n", btv->nr, astat)); IDEBUG(printk ("bttv%d: stat=%08x\n", btv->nr, stat)); @@ -3561,6 +3623,7 @@ } if (stat&(8<<28)) { + btv->gq_start = 0; btv->gq_grab = btv->gqueue[btv->gq_out++]; btv->gq_out = btv->gq_out % MAX_GBUFFERS; if (debug) @@ -3613,7 +3676,9 @@ { IDEBUG(printk ("bttv%d: IRQ_I2CDONE\n", btv->nr)); } - + + btwrite(astat,BT848_INT_STAT); + count++; if (count > 10) printk (KERN_WARNING "bttv%d: irq loop %d\n", @@ -3633,7 +3698,76 @@ * Scan for a Bt848 card, request the irq and map the io memory */ -int configure_bt848(struct pci_dev *dev, int bttv_num) +static void __init bttv_remove(struct pci_dev *pci_dev) +{ + u8 command; + int j; + struct bttv *btv = pci_dev->driver_data; + + /* unregister i2c_bus */ + i2c_bit_del_bus(&btv->i2c_adap); + + /* turn off all capturing, DMA and IRQs */ + btand(~15, BT848_GPIO_DMA_CTL); + + /* first disable interrupts before unmapping the memory! */ + btwrite(0, BT848_INT_MASK); + btwrite(~0x0UL,BT848_INT_STAT); + btwrite(0x0, BT848_GPIO_OUT_EN); + + /* disable PCI bus-mastering */ + pci_read_config_byte(btv->dev, PCI_COMMAND, &command); + /* Should this be &=~ ?? */ + command&=~PCI_COMMAND_MASTER; + pci_write_config_byte(btv->dev, PCI_COMMAND, command); + + /* unmap and free memory */ + for (j = 0; j < gbuffers; j++) + if (btv->gbuf[j].risc) + kfree(btv->gbuf[j].risc); + if (btv->gbuf) + kfree((void *) btv->gbuf); + + if (btv->risc_scr_odd) + kfree((void *) btv->risc_scr_odd); + + if (btv->risc_scr_even) + kfree((void *) btv->risc_scr_even); + + DEBUG(printk(KERN_DEBUG "free: risc_jmp: 0x%p.\n", btv->risc_jmp)); + if (btv->risc_jmp) + kfree((void *) btv->risc_jmp); + + DEBUG(printk(KERN_DEBUG "bt848_vbibuf: 0x%p.\n", btv->vbibuf)); + if (btv->vbibuf) + vfree((void *) btv->vbibuf); + + free_irq(btv->irq,btv); + DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%p.\n", btv->bt848_mem)); + if (btv->bt848_mem) + iounmap(btv->bt848_mem); + + if(btv->video_dev.minor!=-1) + video_unregister_device(&btv->video_dev); + if(btv->vbi_dev.minor!=-1) + video_unregister_device(&btv->vbi_dev); + if (radio[btv->nr] && btv->radio_dev.minor != -1) + video_unregister_device(&btv->radio_dev); + + release_mem_region(btv->bt848_adr, + pci_resource_len(btv->dev,0)); + /* wake up any waiting processes + because shutdown flag is set, no new processes (in this queue) + are expected + */ + btv->shutdown=1; + wake_up(&btv->gpioq); + + return; +} + + +static int __init bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) { int result; unsigned char command; @@ -3642,6 +3776,8 @@ unsigned int cmd; #endif + printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num); + btv=&bttvs[bttv_num]; btv->dev=dev; btv->nr = bttv_num; @@ -3657,15 +3793,15 @@ btv->vbip=VBIBUF_SIZE; init_waitqueue_head(&btv->gpioq); + btv->s_lock = SPIN_LOCK_UNLOCKED; btv->shutdown=0; btv->id=dev->device; btv->irq=dev->irq; - btv->bt848_adr=pci_resource_start(dev, 0); - + btv->bt848_adr=pci_resource_start(dev, 0); if (pci_enable_device(dev)) return -EIO; - if (!request_mem_region(pci_resource_start(dev,0), + if (!request_mem_region(btv->bt848_adr, pci_resource_len(dev,0), "bttv")) { return -EBUSY; @@ -3689,29 +3825,7 @@ cmd = (cmd | PCI_COMMAND_MEMORY ); pci_write_config_dword(dev, PCI_COMMAND, cmd); #endif - - btv->pll.pll_crystal = 0; - btv->pll.pll_ifreq = 0; - btv->pll.pll_ofreq = 0; - btv->pll.pll_current = 0; - if (!(btv->id==848 && btv->revision==0x11)) { - switch (pll[btv->nr]) { - case 0: - /* off */ - break; - case 1: - /* 28 MHz crystal installed */ - btv->pll.pll_ifreq=28636363; - btv->pll.pll_crystal=BT848_IFORM_XT0; - break; - case 2: - /* 35 MHz crystal installed */ - btv->pll.pll_ifreq=35468950; - btv->pll.pll_crystal=BT848_IFORM_XT1; - break; - } - } - + #ifdef __sparc__ btv->bt848_mem=(unsigned char *)btv->bt848_adr; #else @@ -3751,119 +3865,53 @@ if (!(command&BT878_EN_TBFX)) { printk("bttv: 430FX compatibility could not be enabled\n"); + free_irq(btv->irq,btv); result = -1; goto fail; } } + + dev->driver_data = btv; + + if(init_bt848(btv) < 0) { + bttv_remove(dev); + return -EIO; + } + + bttv_num++; + return 0; fail: - release_mem_region(pci_resource_start(btv->dev,0), + release_mem_region(btv->bt848_adr, pci_resource_len(btv->dev,0)); return result; } -static int find_bt848(void) -{ - struct pci_dev *dev; - int result=0; - - bttv_num=0; - - pci_for_each_dev(dev) { - if (dev->vendor == PCI_VENDOR_ID_BROOKTREE) - if ((dev->device == PCI_DEVICE_ID_BT848)|| - (dev->device == PCI_DEVICE_ID_BT849)|| - (dev->device == PCI_DEVICE_ID_BT878)|| - (dev->device == PCI_DEVICE_ID_BT879)) - result=configure_bt848(dev,bttv_num++); - if (result) - return result; - } - if(bttv_num) - printk(KERN_INFO "bttv: %d Bt8xx card(s) found.\n", bttv_num); - return bttv_num; -} - -static void release_bttv(void) -{ - u8 command; - int i,j; - struct bttv *btv; - - for (i=0;ii2c_adap); - - /* turn off all capturing, DMA and IRQs */ - btand(~15, BT848_GPIO_DMA_CTL); - - /* first disable interrupts before unmapping the memory! */ - btwrite(0, BT848_INT_MASK); - btwrite(0xffffffffUL,BT848_INT_STAT); - btwrite(0x0, BT848_GPIO_OUT_EN); - - /* disable PCI bus-mastering */ - pci_read_config_byte(btv->dev, PCI_COMMAND, &command); - /* Should this be &=~ ?? */ - command&=~PCI_COMMAND_MASTER; - pci_write_config_byte(btv->dev, PCI_COMMAND, command); - - /* unmap and free memory */ - for (j = 0; j < gbuffers; j++) - if (btv->gbuf[j].risc) - kfree(btv->gbuf[j].risc); - if (btv->gbuf) - kfree((void *) btv->gbuf); +static struct pci_device_id bttv_pci_tbl[] __initdata = { + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0,} +}; - if (btv->risc_scr_odd) - kfree((void *) btv->risc_scr_odd); - - if (btv->risc_scr_even) - kfree((void *) btv->risc_scr_even); +MODULE_DEVICE_TABLE(pci, bttv_pci_tbl); - DEBUG(printk(KERN_DEBUG "free: risc_jmp: 0x%p.\n", btv->risc_jmp)); - if (btv->risc_jmp) - kfree((void *) btv->risc_jmp); - - DEBUG(printk(KERN_DEBUG "bt848_vbibuf: 0x%p.\n", btv->vbibuf)); - if (btv->vbibuf) - vfree((void *) btv->vbibuf); - - - free_irq(btv->irq,btv); - DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%p.\n", btv->bt848_mem)); - if (btv->bt848_mem) - iounmap(btv->bt848_mem); - - if(btv->video_dev.minor!=-1) - video_unregister_device(&btv->video_dev); - if(btv->vbi_dev.minor!=-1) - video_unregister_device(&btv->vbi_dev); - if (radio[btv->nr] && btv->radio_dev.minor != -1) - video_unregister_device(&btv->radio_dev); - - release_mem_region(pci_resource_start(btv->dev,0), - pci_resource_len(btv->dev,0)); - /* wake up any waiting processes - because shutdown flag is set, no new processes (in this queue) - are expected - */ - btv->shutdown=1; - wake_up(&btv->gpioq); - } -} +static struct pci_driver bttv_pci_driver = { + name:"bttv", + id_table:bttv_pci_tbl, + probe:bttv_probe, + remove:bttv_remove, +}; -#ifdef MODULE -int init_module(void) -#else -int init_bttv_cards(struct video_init *unused) -#endif +static int __init bttv_init_module(void) { - int i; + bttv_num = 0; printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n", (BTTV_VERSION_CODE >> 16) & 0xff, @@ -3878,31 +3926,18 @@ gbuffers,gbufsize/1024,gbuffers*gbufsize/1024); handle_chipset(); - if (find_bt848()<=0) - return -EIO; - - /* initialize Bt848s */ - for (i=0; i #include @@ -143,6 +143,8 @@ int tuner_type; int channel; + + spinlock_t s_lock; unsigned int nr; unsigned short id; @@ -183,7 +185,7 @@ struct bttv_gbuf *gbuf; int gqueue[MAX_GBUFFERS]; - int gq_in,gq_out,gq_grab; + int gq_in,gq_out,gq_grab,gq_start; char *fbuffer; struct bttv_pll_info pll; @@ -272,7 +274,13 @@ #define BTTV_PXELVWPLTVPRO 0x25 #define BTTV_MAGICTVIEW063 0x26 #define BTTV_PINNACLERAVE 0x27 - +#define BTTV_STB2 0x28 +#define BTTV_AVPHONE98 0x29 +#define BTTV_PV951 0x2a + +#define PLL_NONE 0 +#define PLL_28 1 +#define PLL_35 2 #define AUDIO_TUNER 0x00 #define AUDIO_RADIO 0x01 @@ -289,9 +297,11 @@ #define TEA6300 0x04 #define I2C_TSA5522 0xc2 +#define I2C_TDA7432 0x8a +#define I2C_TDA8425 0x82 #define I2C_TDA9840 0x84 #define I2C_TDA9850 0xb6 -#define I2C_TDA8425 0x82 +#define I2C_TDA9875 0xb0 #define I2C_HAUPEE 0xa0 #define I2C_STBEE 0xae #define I2C_VHX 0xc0 diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/epca.c linux/drivers/char/epca.c --- v2.3.99-pre8/linux/drivers/char/epca.c Fri Mar 10 16:40:42 2000 +++ linux/drivers/char/epca.c Mon May 15 12:13:10 2000 @@ -4080,9 +4080,10 @@ { PCI_VENDOR_DIGI, PCI_DEVICE_XEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xem }, { PCI_VENDOR_DIGI, PCI_DEVICE_CX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_cx }, { PCI_VENDOR_DIGI, PCI_DEVICE_XRJ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xrj }, - { 0, }, /* terminate list */ + { 0, } }; +MODULE_DEVICE_TABLE(pci, epca_pci_tbl); int __init init_PCI (void) { /* Begin init_PCI */ diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/generic_serial.c linux/drivers/char/generic_serial.c --- v2.3.99-pre8/linux/drivers/char/generic_serial.c Tue Mar 14 19:10:39 2000 +++ linux/drivers/char/generic_serial.c Sat May 20 10:50:59 2000 @@ -52,6 +52,10 @@ #define RS_EVENT_WRITE_WAKEUP 1 +#ifdef MODULE +MODULE_PARM(gs_debug, "i"); +#endif + #ifdef DEBUG static void my_hd (unsigned char *addr, int len) { @@ -209,12 +213,9 @@ if (!port || !port->xmit_buf || !tmp_buf) return -EIO; - /* printk ("from_user = %d.\n", from_user); */ save_flags(flags); if (from_user) { - /* printk ("Going into the semaphore\n"); */ down(&tmp_buf_sem); - /* printk ("got out of the semaphore\n"); */ while (1) { c = count; @@ -363,19 +364,14 @@ func_exit(); return -EINVAL; /* This is an error which we don't know how to handle. */ } - gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 1\n"); rcib = gs_real_chars_in_buffer(port->tty); - gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 2\n"); - if(rcib <= 0) { gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n"); func_exit(); return rv; } - gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 3\n"); - /* stop trying: now + twice the time it would normally take + seconds */ end_jiffies = jiffies; if (timeout != MAX_SCHEDULE_TIMEOUT) @@ -520,11 +516,10 @@ func_enter (); tty = port->tty; - if (!tty) return; + if (!tty) + return; gs_shutdown_port (port); - - /* gs_flush_buffer (tty); */ port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE |GS_ACTIVE); port->tty = NULL; port->count = 0; @@ -576,7 +571,6 @@ else return -ERESTARTSYS; } - gs_dprintk (GS_DEBUG_BTR, "after hung up\n"); /* @@ -599,7 +593,6 @@ } gs_dprintk (GS_DEBUG_BTR, "after subtype\n"); - /* * If non-blocking mode is set, or the port is not enabled, * then make the check up front and then exit. @@ -613,7 +606,6 @@ } gs_dprintk (GS_DEBUG_BTR, "after nonblock\n"); - if (port->flags & ASYNC_CALLOUT_ACTIVE) { if (port->normal_termios.c_cflag & CLOCAL) do_clocal = 1; @@ -622,8 +614,7 @@ do_clocal = 1; } - gs_dprintk (GS_DEBUG_BTR, "after clocal check.\n"); - + gs_dprintk (GS_DEBUG_BTR, "after clocal check.\n"); /* * Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in @@ -632,10 +623,10 @@ * exit, either normal or abnormal. */ retval = 0; + add_wait_queue(&port->open_wait, &wait); - + gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); - cli(); if (!tty_hung_up_p(filp)) port->count--; @@ -667,7 +658,7 @@ } gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n", port->blocked_open); - current->state = TASK_RUNNING; + set_current_state (TASK_RUNNING); remove_wait_queue(&port->open_wait, &wait); if (!tty_hung_up_p(filp)) port->count++; @@ -687,10 +678,8 @@ struct gs_port *port; func_enter (); - port = (struct gs_port *) tty->driver_data; - gs_dprintk (GS_DEBUG_CLOSE, "tty=%p, port=%p port->tty=%p\n", - tty, port, port->tty); + port = (struct gs_port *) tty->driver_data; if(! port) { func_exit(); @@ -703,9 +692,7 @@ port->tty = tty; } - save_flags(flags); cli(); - if (tty_hung_up_p(filp)) { restore_flags(flags); port->rd->hungup (port); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/lp.c linux/drivers/char/lp.c --- v2.3.99-pre8/linux/drivers/char/lp.c Sat Feb 26 22:31:44 2000 +++ linux/drivers/char/lp.c Mon May 22 09:50:55 2000 @@ -146,13 +146,6 @@ static unsigned int lp_count = 0; -/* Test if printer is ready */ -#define LP_READY(status) ((status) & LP_PBUSY) -/* Test if the printer is not acking the strobe */ -#define LP_NO_ACKING(status) ((status) & LP_PACK) -/* Test if the printer has error conditions */ -#define LP_NO_ERROR(status) ((status) & LP_PERRORP) - #undef LP_DEBUG /* --- low-level port access ----------------------------------- */ @@ -265,6 +258,7 @@ parport_set_timeout (lp_table[minor].dev, lp_table[minor].timeout); + if ((retv = lp_check_status (minor)) == 0) do { /* Write the data. */ written = parport_write (port, kbuf, copy_size); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v2.3.99-pre8/linux/drivers/char/mem.c Tue Apr 11 15:09:16 2000 +++ linux/drivers/char/mem.c Mon May 15 11:19:26 2000 @@ -231,9 +231,10 @@ { unsigned long p = *ppos; ssize_t read = 0; - ssize_t virtr; + ssize_t virtr = 0; + char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */ - if (p < (unsigned long) high_memory) { + if (p < (unsigned long) high_memory) { read = count; if (count > (unsigned long) high_memory - p) read = (unsigned long) high_memory - p; @@ -258,11 +259,27 @@ count -= read; } - virtr = vread(buf, (char *)p, count); - if (virtr < 0) - return virtr; - *ppos += p + virtr; - return virtr + read; + kbuf = (char *)__get_free_page(GFP_KERNEL); + if (!kbuf) + return -ENOMEM; + while (count > 0) { + int len = count; + + if (len > PAGE_SIZE) + len = PAGE_SIZE; + len = vread(kbuf, (char *)p, len); + if (len && copy_to_user(buf, kbuf, len)) { + free_page((unsigned long)kbuf); + return -EFAULT; + } + count -= len; + buf += len; + virtr += len; + p += len; + } + free_page((unsigned long)kbuf); + *ppos = p; + return virtr + read; } /* diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/msp3400.c linux/drivers/char/msp3400.c --- v2.3.99-pre8/linux/drivers/char/msp3400.c Thu May 11 15:30:06 2000 +++ linux/drivers/char/msp3400.c Mon May 15 12:06:25 2000 @@ -871,7 +871,7 @@ /* unmute */ msp3400c_setvolume(client, msp->left, msp->right); - if (msp->watch_stereo) + if (msp->watch_stereo) mod_timer(&msp->wake_stereo, jiffies+5*HZ); if (debug) @@ -1086,7 +1086,7 @@ msp3400c_settreble(client, msp->treble); msp3400c_setvolume(client, msp->left, msp->right); - if (msp->watch_stereo) + if (msp->watch_stereo) mod_timer(&msp->wake_stereo, jiffies+HZ); msp->active = 0; @@ -1236,7 +1236,7 @@ msp3400c_mixer_open(struct inode *inode, struct file *file) { int minor = MINOR(inode->i_rdev); - struct i2c_client *client = NULL; + struct i2c_client *client; struct msp3400c *msp; int i; @@ -1246,12 +1246,12 @@ if (msp->mixer_num == minor) { client = msps[i]; file->private_data = client; - goto match; + break; } } - return -ENODEV; + if (MSP3400_MAX == i) + return -ENODEV; -match: /* lock bttv in memory while the mixer is in use */ if (client->adapter->inc_use) client->adapter->inc_use(client->adapter); @@ -1265,8 +1265,8 @@ { struct i2c_client *client = file->private_data; - if (client->adapter->inc_use) - client->adapter->inc_use(client->adapter); + if (client->adapter->dec_use) + client->adapter->dec_use(client->adapter); MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/func.h linux/drivers/char/rio/func.h --- v2.3.99-pre8/linux/drivers/char/rio/func.h Thu May 11 15:30:06 2000 +++ linux/drivers/char/rio/func.h Sat May 20 10:51:00 2000 @@ -168,4 +168,6 @@ extern int rio_ismodem (kdev_t device); extern void rio_udelay (int usecs); +extern void rio_start_card_running (struct Host * HostP); + #endif /* __func_h_def */ diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/host.h linux/drivers/char/rio/host.h --- v2.3.99-pre8/linux/drivers/char/rio/host.h Thu May 11 15:30:06 2000 +++ linux/drivers/char/rio/host.h Sat May 20 10:51:00 2000 @@ -56,16 +56,16 @@ uchar Mode; /* Control stuff */ uchar Slot; /* Slot */ volatile caddr_t Caddr; /* KV address of DPRAM */ - volatile struct DpRam *CardP; /* KV address of DPRAM, with overlay */ + volatile struct DpRam *CardP; /* KV address of DPRAM, with overlay */ paddr_t PaddrP; /* Phys. address of DPRAM */ char Name[MAX_NAME_LEN]; /* The name of the host */ uint UniqueNum; /* host unique number */ - spinlock_t HostLock; /* Lock structure for MPX */ - /*struct pci_devinfo PciDevInfo; *//* PCI Bus/Device/Function stuff */ + spinlock_t HostLock; /* Lock structure for MPX */ + /*struct pci_devinfo PciDevInfo; *//* PCI Bus/Device/Function stuff */ /*struct lockb HostLock; *//* Lock structure for MPX */ uint WorkToBeDone; /* set to true each interrupt */ uint InIntr; /* Being serviced? */ - uint IntSrvDone; /* host's interrupt has been serviced */ + uint IntSrvDone;/* host's interrupt has been serviced */ int (*Copy)( caddr_t, caddr_t, int ); /* copy func */ struct timer_list timer; /* diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/linux_compat.h linux/drivers/char/rio/linux_compat.h --- v2.3.99-pre8/linux/drivers/char/rio/linux_compat.h Thu May 11 15:30:06 2000 +++ linux/drivers/char/rio/linux_compat.h Sat May 20 10:51:00 2000 @@ -47,7 +47,6 @@ #define SEM_SIGIGNORE 0x1234 - #ifdef DEBUG_SEM #define swait(a,b) printk ("waiting: " __FILE__ " line %d\n", __LINE__) #define ssignal(sem) printk ("signalling: " __FILE__ " line %d\n", __LINE__) diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/rio_linux.c linux/drivers/char/rio/rio_linux.c --- v2.3.99-pre8/linux/drivers/char/rio/rio_linux.c Thu May 11 15:30:06 2000 +++ linux/drivers/char/rio/rio_linux.c Sat May 20 10:55:25 2000 @@ -109,108 +109,6 @@ more than 512 ports.... */ -/* ************************************************************** */ -/* * This section can be removed when 2.0 becomes outdated.... * */ -/* ************************************************************** */ - -#if LINUX_VERSION_CODE < 0x020100 /* Less than 2.1.0 */ -#define TWO_ZERO -#else -#if LINUX_VERSION_CODE < 0x020209 /* less than 2.2.x */ -#warning "Please use a recent 2.2.x kernel. " -#endif -#endif - - -#ifdef TWO_ZERO - -/* Here is the section that makes the 2.2 compatible driver source - work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2, - and provide for compatibility stuff here if possible. */ - -#include - -#define Get_user(a,b) a = get_user(b) -#define Put_user(a,b) 0,put_user(a,b) -#define copy_to_user(a,b,c) memcpy_tofs(a,b,c) - -static inline int copy_from_user(void *to,const void *from, int c) -{ - memcpy_fromfs(to, from, c); - return 0; -} - -#define pci_present pcibios_present -#define pci_read_config_word pcibios_read_config_word -#define pci_read_config_dword pcibios_read_config_dword - -static inline unsigned char get_irq (unsigned char bus, unsigned char fn) -{ - unsigned char t; - pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &t); - return t; -} - -static inline void *ioremap(unsigned long base, long length) -{ - if (base < 0x100000) return (void *)base; - return vremap (base, length); -} - -#define my_iounmap(x, b) (((long)x<0x100000)?0:vfree ((void*)x)) - -#define capable(x) suser() - -#define queue_task queue_task_irq_off -#define tty_flip_buffer_push(tty) queue_task(&tty->flip.tqueue, &tq_timer) -#define signal_pending(current) (current->signal & ~current->blocked) -#define schedule_timeout(to) do {current->timeout = jiffies + (to);schedule ();} while (0) -#define time_after(t1,t2) (((long)t1-t2) > 0) - - -#define test_and_set_bit(nr, addr) set_bit(nr, addr) -#define test_and_clear_bit(nr, addr) clear_bit(nr, addr) - -/* Not yet implemented on 2.0 */ -#define ASYNC_SPD_SHI -1 -#define ASYNC_SPD_WARP -1 - - -/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it - to the "name" field that does exist. As long as the assignments are - done in the right order, there is nothing to worry about. */ -#define driver_name name - -/* Should be in a header somewhere. They are in tty.h on 2.2 */ -#define TTY_HW_COOK_OUT 14 /* Flag to tell ntty what we can handle */ -#define TTY_HW_COOK_IN 15 /* in hardware - output and input */ - -/* The return type of a "close" routine. */ -#define INT void -#define NO_ERROR /* Nothing */ - -#else - -/* The 2.2.x compatibility section. */ -#include - -#define Get_user(a,b) get_user(a,b) -#define Put_user(a,b) put_user(a,b) -#define get_irq(pdev) pdev->irq - -#define INT int -#define NO_ERROR 0 - -#define my_iounmap(x,b) (iounmap((char *)(b))) - -#endif - -/* ************************************************************** */ -/* * End of compatibility section.. * */ -/* ************************************************************** */ - - - /* Why the hell am I defining these here? */ #define RIO_TYPE_NORMAL 1 #define RIO_TYPE_CALLOUT 2 @@ -373,55 +271,15 @@ NULL }; - -/* - This driver can spew a whole lot of debugging output at you. If you - need maximum performance, you should disable the DEBUG define. To - aid in debugging in the field, I'm leaving the compile-time debug - features enabled, and disable them "runtime". That allows me to - instruct people with problems to enable debugging without requiring - them to recompile... -*/ -#define DEBUG - -#ifdef DEBUG -#define rio_dprintk(f, str...) if (rio_debug & f) printk (str) -#else -#define rio_dprintk(f, str...) /* nothing */ -#endif - - -#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ "\n") -#define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit " __FUNCTION__ "\n") - -#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ \ - "(port %d)\n", port->line) - - - - /* * Firmware loader driver specific routines * */ static struct file_operations rio_fw_fops = { - NULL, /* lseek */ - NULL, /* read */ - NULL, /* write */ - NULL, /* readdir */ - NULL, /* select */ - rio_fw_ioctl, - NULL, /* mmap */ - rio_fw_open, -#ifndef TWO_ZERO - NULL, /* flush */ -#endif - rio_fw_release, - NULL, /* fsync */ - NULL, /* fasync */ - NULL, /* check_media_change */ - NULL, /* revalidate */ + ioctl: rio_fw_ioctl, + open: rio_fw_open, + release: rio_fw_release, }; struct miscdevice rio_fw_device = { @@ -446,11 +304,11 @@ KERN_ERR "rio: Warning: null rio port for device %s in %s\n"; if (!port) { - printk(badinfo, kdevname(device), routine); + printk (badinfo, kdevname(device), routine); return 1; } if (port->magic != RIO_MAGIC) { - printk(badmagic, kdevname(device), routine); + printk (badmagic, kdevname(device), routine); return 1; } @@ -468,15 +326,15 @@ unsigned char *addr = ad; for (i=0;i 0x7f)?'.':ch)); + rio_dprintk (RIO_DEBUG_PARAM, "%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch)); } - printk ("\n"); + rio_dprintk (RIO_DEBUG_PARAM, "\n"); } } #else @@ -568,21 +426,26 @@ void rio_reset_interrupt (struct Host *HostP) { + func_enter(); + switch( HostP->Type ) { case RIO_AT: case RIO_MCA: case RIO_PCI: WBYTE(HostP->ResetInt , 0xff); } + + func_exit(); } static void rio_interrupt (int irq, void *ptr, struct pt_regs *regs) { struct Host *HostP; + func_enter (); - HostP = &p->RIOHosts[(long)ptr]; - /* func_enter (); */ + HostP = (struct Host*)ptr; /* &p->RIOHosts[(long)ptr]; */ + rio_dprintk (RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", irq, HostP->Ivec); @@ -627,7 +490,7 @@ } } #endif - + rio_dprintk (RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n"); if (HostP->Ivec == irq) { /* Tell the card we've noticed the interrupt. */ rio_reset_interrupt (HostP); @@ -649,7 +512,7 @@ clear_bit (RIO_BOARD_INTR_LOCK, &HostP->locks); rio_dprintk (RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", irq, HostP->Ivec); - /* func_exit (); */ + func_exit (); } @@ -657,7 +520,7 @@ { func_enter (); - rio_interrupt (0, (void *)data, NULL); + rio_interrupt (0, &p->RIOHosts[data], NULL); p->RIOHosts[data].timer.expires = jiffies + rio_poll; add_timer (&p->RIOHosts[data].timer); @@ -756,11 +619,11 @@ #if 0 port->gs.flags &= ~ GS_ACTIVE; if (!port->gs.tty) { - printk ("No tty.\n"); + rio_dprintk (RIO_DBUG_TTY, "No tty.\n"); return; } if (!port->gs.tty->termios) { - printk ("No termios.\n"); + rio_dprintk (RIO_DEBUG_TTY, "No termios.\n"); return; } if (port->gs.tty->termios->c_cflag & HUPCL) { @@ -1000,6 +863,8 @@ if (rio_debug & RIO_DEBUG_PROBE) my_hd ((char *)&vpdp, 0x20); + + func_exit(); return &vpdp; } @@ -1099,7 +964,7 @@ /* However, the RIO driver allows users to configure their first RTA as the ports numbered 504-511. We therefore need to allocate the whole range. :-( -- REW */ - + #define RI_SZ sizeof(struct rio_info) #define HOST_SZ sizeof(struct Host) #define PORT_SZ sizeof(struct Port *) @@ -1138,11 +1003,20 @@ port->gs.close_delay = HZ/2; port->gs.closing_wait = 30 * HZ; port->gs.rd = &rio_real_driver; + + /* + * Initializing wait queue + */ + init_waitqueue_head(&port->gs.open_wait); + init_waitqueue_head(&port->gs.close_wait); + } #else /* We could postpone initializing them to when they are configured. */ #endif + + if (rio_debug & RIO_DEBUG_INIT) { my_hd (&rio_real_driver, sizeof (rio_real_driver)); } @@ -1166,7 +1040,6 @@ } -#ifdef MODULE static void rio_release_drivers(void) { func_enter(); @@ -1176,7 +1049,6 @@ tty_unregister_driver (&rio_driver); func_exit(); } -#endif #ifdef TWO_ZERO #define PDEV unsigned char pci_bus, unsigned pci_fun @@ -1213,7 +1085,7 @@ unsigned int t; #define CNTRL_REG_OFFSET 0x50 -#define CNTRL_REG_GOODVALUE 0x00260000 +#define CNTRL_REG_GOODVALUE 0x18260000 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase); hwbase &= PCI_BASE_ADDRESS_MEM_MASK; @@ -1294,7 +1166,6 @@ pci_read_config_dword (pdev, 0x2c, &tint); tshort = (tint >> 16) & 0xffff; rio_dprintk (RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint); - /* rio_dprintk (RIO_DEBUG_PROBE, "pdev = %d/%d (%x)\n", pdev, tint); */ if (tshort != 0x0100) { rio_dprintk (RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", tshort); @@ -1307,49 +1178,51 @@ hp = &p->RIOHosts[p->RIONumHosts]; hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK; hp->Ivec = get_irq (pdev); - if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; + if (((1 << hp->Ivec) & rio_irqmask) == 0) + hp->Ivec = 0; hp->CardP = (struct DpRam *) hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); hp->Type = RIO_PCI; hp->Copy = rio_pcicopy; - hp->Mode = RIO_PCI_DEFAULT_MODE; - + hp->Mode = RIO_PCI_BOOT_FROM_RAM; + rio_reset_interrupt (hp); + rio_start_card_running (hp); + rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *)p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr); if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0 ) == RIO_SUCCESS) { - WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff); - p->RIOHosts[p->RIONumHosts].UniqueNum = - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)| - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)| - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)| - ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24); - rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", - p->RIOHosts[p->RIONumHosts].UniqueNum); - -#if 1 - fix_rio_pci (pdev); -#endif - p->RIOLastPCISearch = RIO_SUCCESS; - p->RIONumHosts++; - found++; + rio_dprintk (RIO_DEBUG_INIT, "Done RIOBoardTest\n"); + WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff); + p->RIOHosts[p->RIONumHosts].UniqueNum = + ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)| + ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)| + ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)| + ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24); + rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", + p->RIOHosts[p->RIONumHosts].UniqueNum); + + fix_rio_pci (pdev); + p->RIOLastPCISearch = RIO_SUCCESS; + p->RIONumHosts++; + found++; } else { - my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, - p->RIOHosts[p->RIONumHosts].Caddr); + my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, + p->RIOHosts[p->RIONumHosts].Caddr); } - + #ifdef TWO_ZERO } /* We have two variants with the opening brace, so to prevent */ #else } /* Emacs from getting confused we have two closing braces too. */ #endif - /* Then look for the older PCI card.... : */ #ifndef TWO_ZERO + /* These older PCI cards have problems (only byte-mode access is supported), which makes them a bit awkward to support. They also have problems sharing interrupts. Be careful. @@ -1374,15 +1247,21 @@ hp = &p->RIOHosts[p->RIONumHosts]; hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK; hp->Ivec = get_irq (pdev); - if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; + if (((1 << hp->Ivec) & rio_irqmask) == 0) + hp->Ivec = 0; hp->Ivec |= 0x8000; /* Mark as non-sharable */ hp->CardP = (struct DpRam *) hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); hp->Type = RIO_PCI; hp->Copy = rio_pcicopy; - hp->Mode = RIO_PCI_DEFAULT_MODE; - - rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", + hp->Mode = RIO_PCI_BOOT_FROM_RAM; + + rio_dprintk (RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec); + rio_dprintk (RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode); + + rio_reset_interrupt (hp); + rio_start_card_running (hp); + rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *)p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr); if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP, @@ -1425,11 +1304,15 @@ hp->CardP = (struct DpRam *) hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN); hp->Type = RIO_AT; - hp->Copy = rio_pcicopy; + hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL + * -- YES! this is now a normal copy. Only the + * old PCI card uses the special PCI copy. + * Moreover, the ISA card will work with the + * special PCI copy anyway. -- REW */ hp->Mode = 0; vpdp = get_VPD_PROM (hp); - + rio_dprintk (RIO_DEBUG_PROBE, "Got VPD ROM\n"); okboard = 0; if ((strncmp (vpdp->identifier, RIO_ISA_IDENT, 16) == 0) || (strncmp (vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) || @@ -1460,11 +1343,21 @@ if (hp->Ivec) { int mode = SA_SHIRQ; if (hp->Ivec & 0x8000) {mode = 0; hp->Ivec &= 0x7fff;} - if (request_irq (hp->Ivec, rio_interrupt, mode, "rio", (void *)i)) { - printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec); - hp->Ivec = 0; + rio_dprintk (RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp,hp->Ivec, hp->Mode); + retval = request_irq (hp->Ivec, rio_interrupt, mode, "rio", hp); + rio_dprintk (RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval); + if (retval) { + printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec); + hp->Ivec = 0; } rio_dprintk (RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec); + if (hp->Ivec != 0){ + rio_dprintk (RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n"); + hp->Mode |= RIO_PCI_INT_ENABLE; + } else + hp->Mode &= !RIO_PCI_INT_ENABLE; + rio_dprintk (RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode); + rio_start_card_running (hp); } /* Init the timer "always" to make sure that it can safely be deleted when we unload... */ @@ -1481,7 +1374,7 @@ } if (found) { - printk (KERN_INFO "rio: total of %d boards detected.\n", found); + rio_dprintk (RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found); if (misc_register(&rio_fw_device) < 0) { printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n"); @@ -1506,7 +1399,7 @@ for (i=0,hp=p->RIOHosts;iRIONumHosts;i++, hp++) { RIOHostReset (hp->Type, hp->CardP, hp->Slot); if (hp->Ivec) { - free_irq (hp->Ivec, (void *)i); + free_irq (hp->Ivec, hp); rio_dprintk (RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec); } /* It is safe/allowed to del_timer a non-active timer */ diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/rio_linux.h linux/drivers/char/rio/rio_linux.h --- v2.3.99-pre8/linux/drivers/char/rio/rio_linux.h Thu May 11 15:30:06 2000 +++ linux/drivers/char/rio/rio_linux.h Sun May 21 20:55:06 2000 @@ -23,13 +23,13 @@ * Version 1.0 -- July, 1999. * */ +#include #define RIO_NBOARDS 4 #define RIO_PORTSPERBOARD 128 #define RIO_NPORTS (RIO_NBOARDS * RIO_PORTSPERBOARD) #ifdef __KERNEL__ -#include #define RIO_MAGIC 0x12345678 @@ -158,5 +158,30 @@ #else #define rio_memcpy_toio(dummy,dest,source,n) memcpy_toio(dest, source, n) #define rio_memcpy_fromio memcpy_fromio +#endif + +#define DEBUG + + +/* + This driver can spew a whole lot of debugging output at you. If you + need maximum performance, you should disable the DEBUG define. To + aid in debugging in the field, I'm leaving the compile-time debug + features enabled, and disable them "runtime". That allows me to + instruct people with problems to enable debugging without requiring + them to recompile... +*/ + +#ifdef DEBUG +#define rio_dprintk(f, str...) if (rio_debug & f) printk (str) +#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ "\n") +#define func_exit() rio_dprintk (RIO_DEBUG_FLOW, "rio: exit " __FUNCTION__ "\n") +#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ \ + "(port %d)\n", port->line) +#else +#define rio_dprintk(f, str...) /* nothing */ +#define func_enter() +#define func_exit() +#define func_enter2() #endif diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/rioboot.c linux/drivers/char/rio/rioboot.c --- v2.3.99-pre8/linux/drivers/char/rio/rioboot.c Thu May 11 15:30:06 2000 +++ linux/drivers/char/rio/rioboot.c Sun May 21 20:55:06 2000 @@ -81,7 +81,6 @@ #include "cmdblk.h" #include "route.h" - static uchar RIOAtVec2Ctrl[] = { @@ -113,6 +112,8 @@ { int offset; + func_enter (); + /* Linux doesn't allow you to disable interrupts during a "copyin". (Crash when a pagefault occurs). */ /* disable(oldspl); */ @@ -126,6 +127,7 @@ rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot Code Too Large!\n")); p->RIOError.Error = HOST_FILE_TOO_LARGE; /* restore(oldspl); */ + func_exit (); return ENOMEM; } @@ -133,6 +135,7 @@ rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot Code : BUSY BUSY BUSY!\n")); p->RIOError.Error = BOOT_IN_PROGRESS; /* restore(oldspl); */ + func_exit (); return EBUSY; } @@ -160,6 +163,7 @@ rio_dprint(RIO_DEBUG_BOOT, ("Bad data copy from user space\n")); p->RIOError.Error = COPYIN_FAILED; /* restore(oldspl); */ + func_exit (); return EFAULT; } @@ -171,9 +175,61 @@ p->RIOBootCount = rbp->Count; /* restore(oldspl); */ + func_exit(); return 0; } +void rio_start_card_running (struct Host * HostP) +{ + func_enter (); + + switch ( HostP->Type ) { + case RIO_AT: + rio_dprint(RIO_DEBUG_BOOT, ("Start ISA card running\n")); + WBYTE(HostP->Control, + BOOT_FROM_RAM | EXTERNAL_BUS_ON + | HostP->Mode + | RIOAtVec2Ctrl[HostP->Ivec & 0xF] ); + break; + +#ifdef FUTURE_RELEASE + case RIO_MCA: + /* + ** MCA handles IRQ vectors differently, so we don't write + ** them to this register. + */ + rio_dprint(RIO_DEBUG_BOOT, ("Start MCA card running\n")); + WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode); + break; + + case RIO_EISA: + /* + ** EISA is totally different and expects OUTBZs to turn it on. + */ + rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_DAEMON,"Start EISA card running\n"); + OUTBZ( HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM ); + break; +#endif + + case RIO_PCI: + /* + ** PCI is much the same as MCA. Everything is once again memory + ** mapped, so we are writing to memory registers instead of io + ** ports. + */ + rio_dprint(RIO_DEBUG_BOOT, ("Start PCI card running\n")); + WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode); + break; + default: + rio_dprint(RIO_DEBUG_BOOT, ("Unknown host type %d\n",HostP->Type)); + break; + } +/* + printk (KERN_INFO "Done with starting the card\n"); + func_exit (); +*/ + return; +} /* ** Load in the host boot code - load it directly onto all halted hosts @@ -206,6 +262,10 @@ for ( host=0; hostRIONumHosts; host++ ) { rio_dprint(RIO_DEBUG_BOOT, ("Attempt to boot host %d\n",host)); HostP = &p->RIOHosts[host]; + + rio_dprint(RIO_DEBUG_BOOT, ("Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", + HostP->Type, HostP->Mode, HostP->Ivec ) ); + if ( (HostP->Flags & RUN_STATE) != RC_WAITING ) { rio_dprint(RIO_DEBUG_BOOT, ("%s %d already running\n","Host",host)); @@ -233,6 +293,7 @@ if ( p->RIOConf.HostLoadBase < rbp->Count ) { rio_dprint(RIO_DEBUG_BOOT, ("Bin too large\n")); p->RIOError.Error = HOST_FILE_TOO_LARGE; + func_exit (); return EFBIG; } /* @@ -259,6 +320,7 @@ if ( !DownCode ) { rio_dprint(RIO_DEBUG_BOOT, ("No system memory available\n")); p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY; + func_exit (); return ENOMEM; } bzero(DownCode, rbp->Count); @@ -266,6 +328,7 @@ if ( copyin((int)rbp->DataP,DownCode,rbp->Count)==COPYFAIL ) { rio_dprint(RIO_DEBUG_BOOT, ("Bad copyin of host data\n")); p->RIOError.Error = COPYIN_FAILED; + func_exit (); return EFAULT; } @@ -276,6 +339,7 @@ else if ( copyin((int)rbp->DataP,StartP,rbp->Count)==COPYFAIL ) { rio_dprint(RIO_DEBUG_BOOT, ("Bad copyin of host data\n")); p->RIOError.Error = COPYIN_FAILED; + func_exit (); return EFAULT; } @@ -405,47 +469,8 @@ rio_dprint(RIO_DEBUG_BOOT, ("Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec ) ); - switch ( HostP->Type ) { - case RIO_AT: - rio_dprint(RIO_DEBUG_BOOT, ("Start ISA card running\n")); - WBYTE(HostP->Control, - BOOT_FROM_RAM | EXTERNAL_BUS_ON - | HostP->Mode - | RIOAtVec2Ctrl[HostP->Ivec & 0xF] ); - break; - -#ifdef FUTURE_RELEASE - case RIO_MCA: - /* - ** MCA handles IRQ vectors differently, so we don't write - ** them to this register. - */ - rio_dprint(RIO_DEBUG_BOOT, ("Start MCA card running\n")); - WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode); - break; - - case RIO_EISA: - /* - ** EISA is totally different and expects OUTBZs to turn it on. - */ - rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_DAEMON,"Start EISA card running\n"); - OUTBZ( HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM ); - break; -#endif + rio_start_card_running(HostP); - case RIO_PCI: - /* - ** PCI is much the same as MCA. Everything is once again memory - ** mapped, so we are writing to memory registers instead of io - ** ports. - */ - rio_dprint(RIO_DEBUG_BOOT, ("Start PCI card running\n")); - WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode); - break; - default: - rio_dprint(RIO_DEBUG_BOOT, ("Unknown host type %d\n",HostP->Type)); - break; - } rio_dprint(RIO_DEBUG_BOOT, ("Set control port\n")); /* @@ -453,9 +478,10 @@ ** pointer: */ for ( wait_count=0; (wait_countRIOConf.StartupTime)&& - (RWORD(HostP->__ParmMapR)==OldParmMap); wait_count++ ) { + (RWORD(HostP->__ParmMapR)==OldParmMap); wait_count++ ) { rio_dprint(RIO_DEBUG_BOOT, ("Checkout %d, 0x%x\n",wait_count,RWORD(HostP->__ParmMapR))); delay(HostP, HUNDRED_MS); + } /* @@ -613,6 +639,7 @@ p->RIOSystemUp++; rio_dprint(RIO_DEBUG_BOOT, ("Done everything %x\n", HostP->Ivec)); + func_exit (); return 0; } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/riocmd.c linux/drivers/char/rio/riocmd.c --- v2.3.99-pre8/linux/drivers/char/rio/riocmd.c Thu May 11 15:30:06 2000 +++ linux/drivers/char/rio/riocmd.c Sun May 21 20:55:06 2000 @@ -43,7 +43,6 @@ #include #include - #include #include diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/rioctrl.c linux/drivers/char/rio/rioctrl.c --- v2.3.99-pre8/linux/drivers/char/rio/rioctrl.c Thu May 11 15:30:06 2000 +++ linux/drivers/char/rio/rioctrl.c Sun May 21 20:55:06 2000 @@ -201,6 +201,8 @@ int retval = 0; unsigned long flags; + func_enter (); + /* Confuse teh compiler to think that we've initialized these */ Host=0; PortP = NULL; @@ -1776,6 +1778,8 @@ } rio_dprint(RIO_DEBUG_CTRL, ("INVALID DAEMON IOCTL 0x%x\n",cmd)); p->RIOError.Error = IOCTL_COMMAND_UNKNOWN; + + func_exit (); return EINVAL; } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/rioinit.c linux/drivers/char/rio/rioinit.c --- v2.3.99-pre8/linux/drivers/char/rio/rioinit.c Thu May 11 15:30:06 2000 +++ linux/drivers/char/rio/rioinit.c Sat May 20 10:51:00 2000 @@ -1414,7 +1414,7 @@ (int)p->RIOHosts, sizeof(struct Host) ) ); for( host=0; hostRIOHosts[host].HostLock = SPIN_LOCK_UNLOCKED; /* Let the first guy takes it */ + spin_lock_init (&p->RIOHosts[host].HostLock); p->RIOHosts[host].timeout_id = 0; /* Let the first guy takes it */ } /* diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/riotty.c linux/drivers/char/rio/riotty.c --- v2.3.99-pre8/linux/drivers/char/rio/riotty.c Thu May 11 15:30:07 2000 +++ linux/drivers/char/rio/riotty.c Sun May 21 20:55:06 2000 @@ -89,7 +89,6 @@ #include "list.h" #include "sam.h" - #if 0 static void ttyseth_pv(struct Port *, struct ttystatics *, struct termios *sg, int); @@ -154,13 +153,21 @@ unsigned long flags; int retval = 0; + func_enter (); + + /* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close + is going to oops. + */ + tty->driver_data = NULL; + SysPort = rio_minor (tty->device); Modem = rio_ismodem (tty->device); if ( p->RIOFailed ) { rio_dprint(RIO_DEBUG_TTY, ("System initialisation failed\n")); pseterr(ENXIO); - return 0; + func_exit (); + return -ENXIO; } rio_dprint(RIO_DEBUG_TTY, ("port open SysPort %d (%s) (mapped:%d)\n", @@ -176,22 +183,24 @@ if (SysPort >= RIO_PORTS) { /* out of range ? */ rio_dprint(RIO_DEBUG_TTY, ("Illegal port number %d\n",SysPort)); pseterr(ENXIO); - return 0; + func_exit(); + return -ENXIO; } /* ** Grab pointer to the port stucture */ PortP = p->RIOPortp[SysPort]; /* Get control struc */ - + rio_dprintk (RIO_DEBUG_TTY, "PortP: %p\n", PortP); if ( !PortP->Mapped ) { /* we aren't mapped yet! */ /* ** The system doesn't know which RTA this port ** corresponds to. */ rio_dprint(RIO_DEBUG_TTY, ("port not mapped into system\n")); + func_exit (); pseterr(ENXIO); - return 0; + return -ENXIO; } tty->driver_data = PortP; @@ -209,7 +218,8 @@ if ( (PortP->HostP->Flags & RUN_STATE) != RC_RUNNING ) { rio_dprint(RIO_DEBUG_TTY, ("Host not running\n")); pseterr(ENXIO); - return 0; + func_exit (); + return -ENXIO; } /* @@ -224,12 +234,14 @@ do { if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { rio_dprint(RIO_DEBUG_TTY, ("RTA EINTR in delay \n")); + func_exit (); return -EINTR; } if (repeat_this -- <= 0) { rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot timeout\n")); RIOPreemptiveCmd(p, PortP, FCLOSE ); pseterr(EINTR); + func_exit (); return -EIO; } } while(!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)); @@ -237,6 +249,7 @@ } else { rio_dprint(RIO_DEBUG_TTY, ("RTA never booted\n")); pseterr(ENXIO); + func_exit (); return 0; } } @@ -249,6 +262,7 @@ while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) { if (!PortP->WaitUntilBooted) { rio_dprint(RIO_DEBUG_TTY, ("RTA never booted\n")); + func_exit (); return -ENXIO; } @@ -258,10 +272,12 @@ */ if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { rio_dprint(RIO_DEBUG_TTY, ("RTA_wait_for_boot: EINTR in delay \n")); + func_exit (); return -EINTR; } if (repeat_this -- <= 0) { rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot timeout\n")); + func_exit (); return -EIO; } } @@ -276,8 +292,10 @@ } #if 0 retval = gs_init_port(&PortP->gs); - if (retval) - return retval; + if (retval){ + func_exit (); + return retval; + } #endif /* @@ -306,6 +324,7 @@ rio_dprint(RIO_DEBUG_TTY, ("Port unmapped while closing!\n")); rio_spin_unlock_irqrestore(&PortP->portSem, flags); retval = -ENXIO; + func_exit (); return retval; } @@ -375,6 +394,7 @@ if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { rio_dprint(RIO_DEBUG_TTY, ("Waiting for open to finish broken by signal\n")); RIOPreemptiveCmd(p, PortP, FCLOSE ); + func_exit (); return -EINTR; } rio_spin_lock_irqsave(&PortP->portSem, flags); @@ -425,6 +445,7 @@ tp->tm.c_state &= ~WOPEN; PortP->State &= ~RIO_WOPEN; rio_spin_unlock_irqrestore(&PortP->portSem, flags); + func_exit (); return -EINTR; } } @@ -462,6 +483,7 @@ rio_spin_unlock_irqrestore(&PortP->portSem, flags); rio_dprint(RIO_DEBUG_TTY, ("Returning from open\n")); + func_exit (); return 0; } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/unixrup.h linux/drivers/char/rio/unixrup.h --- v2.3.99-pre8/linux/drivers/char/rio/unixrup.h Thu May 11 15:30:07 2000 +++ linux/drivers/char/rio/unixrup.h Sat May 20 10:51:00 2000 @@ -49,7 +49,7 @@ uint Id; /* Id number */ uint BaseSysPort; /* SysPort of first tty on this RTA */ uint ModTypes; /* Modules on this RTA */ - spinlock_t RupLock; /* Lock structure for MPX */ + spinlock_t RupLock; /* Lock structure for MPX */ /* struct lockb RupLock; */ /* Lock structure for MPX */ }; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rtc.c linux/drivers/char/rtc.c --- v2.3.99-pre8/linux/drivers/char/rtc.c Thu May 11 15:30:07 2000 +++ linux/drivers/char/rtc.c Sat May 20 09:27:06 2000 @@ -760,7 +760,7 @@ static void rtc_dropped_irq(unsigned long data) { - printk(KERN_INFO "rtc: lost some interrupts at %ldHz.\n", rtc_freq); + unsigned long freq; spin_lock_irq (&rtc_lock); @@ -771,7 +771,12 @@ rtc_irq_data += ((rtc_freq/HZ)<<8); rtc_irq_data &= ~0xff; rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */ + + freq = rtc_freq; + spin_unlock_irq(&rtc_lock); + + printk(KERN_INFO "rtc: lost some interrupts at %ldHz.\n", freq); /* Now we have new data */ wake_up_interruptible(&rtc_wait); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/sh-sci.c linux/drivers/char/sh-sci.c --- v2.3.99-pre8/linux/drivers/char/sh-sci.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/char/sh-sci.c Sat May 20 12:05:30 2000 @@ -189,10 +189,35 @@ ctrl_out(smr_val, SCSMR); #if defined(CONFIG_SH_SCIF_SERIAL) +#if defined(__sh3__) + { /* For SH7709, SH7709A, SH7729 */ + unsigned short data; + + /* We need to set SCPCR to enable RTS/CTS */ + data = ctrl_inw(SCPCR); + /* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/ + ctrl_outw(data&0x0fcf, SCPCR); + } +#endif if (C_CRTSCTS(port->gs.tty)) fcr_val |= 0x08; - else + else { +#if defined(__sh3__) + unsigned short data; + + /* We need to set SCPCR to enable RTS/CTS */ + data = ctrl_inw(SCPCR); + /* Clear out SCP7MD1,0, SCP4MD1,0, + Set SCP6MD1,0 = {01} (output) */ + ctrl_outw((data&0x0fcf)|0x1000, SCPCR); + + data = ctrl_inb(SCPDR); + /* Set /RTS2 (bit6) = 0 */ + ctrl_outb(data&0xbf, SCPDR); +#elif defined(__SH4__) ctrl_outw(0x0080, SCSPTR); /* Set RTS = 1 */ +#endif + } ctrl_out(fcr_val, SCFCR); #endif @@ -721,7 +746,7 @@ int i; for (i=SCI_ERI_IRQ; igs.tty; while (1) { rx_op = sx_read_channel_byte (port, hi_rxopos); @@ -1134,7 +1134,7 @@ /* tty_schedule_flip (tty); */ } - /* func_exit (); */ + func_exit (); } /* Inlined: it is called only once. Remove the inline if you add another @@ -2343,6 +2343,12 @@ #ifdef NEW_WRITE_LOCKING port->gs.port_write_sem = MUTEX; #endif + /* + * Initializing wait queue + */ + init_waitqueue_head(&port->gs.open_wait); + init_waitqueue_head(&port->gs.close_wait); + port++; } } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/tda7432.c linux/drivers/char/tda7432.c --- v2.3.99-pre8/linux/drivers/char/tda7432.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/tda7432.c Mon May 15 12:06:25 2000 @@ -0,0 +1,505 @@ +/* + * For the STS-Thompson TDA7432 audio processor chip + * + * Handles audio functions: volume, balance, tone, loudness + * This driver will not complain if used with any + * other i2c device with the same address. + * + * Copyright (c) 2000 Eric Sandeen + * This code is placed under the terms of the GNU General Public License + * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) + * Which was based on tda8425.c by Greg Alexander (c) 1998 + * + * OPTIONS: + * debug - set to 1 if you'd like to see debug messages + * set to 2 if you'd like to be inundated with debug messages + * + * loudness - set between 0 and 15 for varying degrees of loudness effect + * + * TODO: + * Implement tone controls + * + * Revision: 0.3 - Fixed silly reversed volume controls. :) + * Revision: 0.2 - Cleaned up #defines + * fixed volume control + * Added I2C_DRIVERID_TDA7432 + * added loudness insmod control + * Revision: 0.1 - initial version + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bttv.h" +#include "audiochip.h" + +/* This driver ID is brand new, so define it if it's not in i2c-id.h yet */ +#ifndef I2C_DRIVERID_TDA7432 + #define I2C_DRIVERID_TDA7432 27 +#endif + + +MODULE_AUTHOR("Eric Sandeen "); +MODULE_DESCRIPTION("bttv driver for the tda7432 audio processor chip"); + +MODULE_PARM(debug,"i"); +MODULE_PARM(loudness,"i"); +static int loudness = 0; /* disable loudness by default */ +static int debug = 0; /* insmod parameter */ + + +/* Address to scan (I2C address of this chip) */ +static unsigned short normal_i2c[] = { + I2C_TDA7432 >> 1, + I2C_CLIENT_END}; +static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; +static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static struct i2c_client_address_data addr_data = { + normal_i2c, normal_i2c_range, + probe, probe_range, + ignore, ignore_range, + force +}; + +/* Structure of address and subaddresses for the tda7432 */ + +struct tda7432 { + int addr; + int input; + int volume; + int tone; + int lf, lr, rf, rr; + int loud; +}; + +static struct i2c_driver driver; +static struct i2c_client client_template; + +#define dprintk if (debug) printk +#define d2printk if (debug > 1) printk + +/* The TDA7432 is made by STS-Thompson + * http://www.st.com + * http://us.st.com/stonline/books/pdf/docs/4056.pdf + * + * TDA7432: I2C-bus controlled basic audio processor + * + * The TDA7432 controls basic audio functions like volume, balance, + * and tone control (including loudness). It also has four channel + * output (for front and rear). Since most vidcap cards probably + * don't have 4 channel output, this driver will set front & rear + * together (no independent control). + */ + + /* Subaddresses for TDA7432 */ + +#define TDA7432_IN 0x00 /* Input select */ +#define TDA7432_VL 0x01 /* Volume */ +#define TDA7432_TN 0x02 /* Bass, Treble (Tone) */ +#define TDA7432_LF 0x03 /* Attenuation LF (Left Front) */ +#define TDA7432_LR 0x04 /* Attenuation LR (Left Rear) */ +#define TDA7432_RF 0x05 /* Attenuation RF (Right Front) */ +#define TDA7432_RR 0x06 /* Attenuation RR (Right Rear) */ +#define TDA7432_LD 0x07 /* Loudness */ + + + /* Masks for bits in TDA7432 subaddresses */ + +/* Many of these not used - just for documentation */ + +/* Subaddress 0x00 - Input selection and bass control */ + +/* Bits 0,1,2 control input: + * 0x00 - Stereo input + * 0x02 - Mono input + * 0x03 - Mute + * Mono probably isn't used - I'm guessing only the stereo + * input is connected on most cards, so we'll set it to stereo. + * + * Bit 3 controls bass cut: 0/1 is non-symmetric/symmetric bass cut + * Bit 4 controls bass range: 0/1 is extended/standard bass range + * + * Highest 3 bits not used + */ + +#define TDA7432_STEREO_IN 0 +#define TDA7432_MONO_IN 2 /* Probably won't be used */ +#define TDA7432_MUTE 3 /* Probably won't be used */ +#define TDA7432_BASS_SYM 1 << 3 +#define TDA7432_BASS_NORM 1 << 4 + +/* Subaddress 0x01 - Volume */ + +/* Lower 7 bits control volume from -79dB to +32dB in 1dB steps + * Recommended maximum is +20 dB + * + * +32dB: 0x00 + * +20dB: 0x0c + * 0dB: 0x20 + * -79dB: 0x6f + * + * MSB (bit 7) controls loudness: 1/0 is loudness on/off + */ + +#define TDA7432_VOL_0DB 0x20 +#define TDA7432_LD_ON 1 << 7 + + +/* Subaddress 0x02 - Tone control */ + +/* Bits 0,1,2 control absolute treble gain from 0dB to 14dB + * 0x0 is 14dB, 0x7 is 0dB + * + * Bit 3 controls treble attenuation/gain (sign) + * 1 = gain (+) + * 0 = attenuation (-) + * + * Bits 4,5,6 control absolute bass gain from 0dB to 14dB + * (This is only true for normal base range, set in 0x00) + * 0x0 << 4 is 14dB, 0x7 is 0dB + * + * Bit 7 controls bass attenuation/gain (sign) + * 1 << 7 = gain (+) + * 0 << 7 = attenuation (-) + * + * Example: + * 1 1 0 1 0 1 0 1 is +4dB bass, -4dB treble + */ + +#define TDA7432_TREBLE_0DB 0xf +#define TDA7432_TREBLE 7 +#define TDA7432_TREBLE_GAIN 1 << 3 +#define TDA7432_BASS_0DB 0xf << 4 +#define TDA7432_BASS 7 << 4 +#define TDA7432_BASS_GAIN 1 << 7 + + +/* Subaddress 0x03 - Left Front attenuation */ +/* Subaddress 0x04 - Left Rear attenuation */ +/* Subaddress 0x05 - Right Front attenuation */ +/* Subaddress 0x06 - Right Rear attenuation */ + +/* Bits 0,1,2,3,4 control attenuation from 0dB to -37.5dB + * in 1.5dB steps. + * + * 0x00 is 0dB + * 0x1f is -37.5dB + * + * Bit 5 mutes that channel when set (1 = mute, 0 = unmute) + * We'll use the mute on the input, though (above) + * Bits 6,7 unused + */ + +#define TDA7432_ATTEN_0DB 0x00 + + +/* Subaddress 0x07 - Loudness Control */ + +/* Bits 0,1,2,3 control loudness from 0dB to -15dB in 1dB steps + * when bit 4 is NOT set + * + * 0x0 is 0dB + * 0xf is -15dB + * + * If bit 4 is set, then there is a flat attenuation according to + * the lower 4 bits, as above. + * + * Bits 5,6,7 unused + */ + + + +/* Begin code */ + +static int tda7432_write(struct i2c_client *client, int subaddr, int val) +{ + unsigned char buffer[2]; + d2printk("tda7432: In tda7432_write\n"); + dprintk("tda7432: Writing %d 0x%x\n", subaddr, val); + buffer[0] = subaddr; + buffer[1] = val; + if (2 != i2c_master_send(client,buffer,2)) { + printk(KERN_WARNING "tda7432: I/O error, trying (write %d 0x%x)\n", + subaddr, val); + return -1; + } + return 0; +} + +/* I don't think we ever actually _read_ the chip... */ +#if 0 +static int tda7432_read(struct i2c_client *client) +{ + unsigned char buffer; + d2printk("tda7432: In tda7432_read\n"); + if (1 != i2c_master_recv(client,&buffer,1)) { + printk(KERN_WARNING "tda7432: I/O error, trying (read)\n"); + return -1; + } + dprintk("tda7432: Read 0x%02x\n", buffer); + return buffer; +} +#endif + +static int tda7432_set(struct i2c_client *client) +{ + struct tda7432 *t = client->data; + unsigned char buf[16]; + d2printk("tda7432: In tda7432_set\n"); + + dprintk(KERN_INFO + "tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", + t->input,t->volume,t->tone,t->lf,t->lr,t->rf,t->rr,t->loud); + buf[0] = TDA7432_IN; + buf[1] = t->input; + buf[2] = t->volume; + buf[3] = t->tone; + buf[4] = t->lf; + buf[5] = t->lr; + buf[6] = t->rf; + buf[7] = t->rr; + buf[8] = t->loud; + if (9 != i2c_master_send(client,buf,9)) { + printk(KERN_WARNING "tda7432: I/O error, trying tda7432_set\n"); + return -1; + } + + return 0; +} + +static void do_tda7432_init(struct i2c_client *client) +{ + struct tda7432 *t = client->data; + d2printk("tda7432: In tda7432_init\n"); + + t->input = TDA7432_STEREO_IN | /* Main (stereo) input */ + TDA7432_BASS_SYM | /* Symmetric bass cut */ + TDA7432_BASS_NORM; /* Normal bass range */ + t->volume = TDA7432_VOL_0DB; /* 0dB Volume */ + if (loudness) /* Turn loudness on? */ + t->volume |= TDA7432_LD_ON; + t->tone = TDA7432_TREBLE_0DB | /* 0dB Treble */ + TDA7432_BASS_0DB; /* 0dB Bass */ + t->lf = TDA7432_ATTEN_0DB; /* 0dB attenuation */ + t->lr = TDA7432_ATTEN_0DB; /* 0dB attenuation */ + t->rf = TDA7432_ATTEN_0DB; /* 0dB attenuation */ + t->rr = TDA7432_ATTEN_0DB; /* 0dB attenuation */ + t->loud = loudness; /* insmod parameter */ + + tda7432_set(client); +} + +/* *********************** * + * i2c interface functions * + * *********************** */ + +static int tda7432_attach(struct i2c_adapter *adap, int addr, + unsigned short flags, int kind) +{ + struct tda7432 *t; + struct i2c_client *client; + d2printk("tda7432: In tda7432_attach\n"); + client = kmalloc(sizeof *client,GFP_KERNEL); + if (!client) + return -ENOMEM; + memcpy(client,&client_template,sizeof(struct i2c_client)); + client->adapter = adap; + client->addr = addr; + + client->data = t = kmalloc(sizeof *t,GFP_KERNEL); + if (!t) + return -ENOMEM; + memset(t,0,sizeof *t); + do_tda7432_init(client); + MOD_INC_USE_COUNT; + strcpy(client->name,"TDA7432"); + printk(KERN_INFO "tda7432: init\n"); + + i2c_attach_client(client); + return 0; +} + +static int tda7432_probe(struct i2c_adapter *adap) +{ + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + return i2c_probe(adap, &addr_data, tda7432_attach); + return 0; +} + +static int tda7432_detach(struct i2c_client *client) +{ + struct tda7432 *t = client->data; + + do_tda7432_init(client); + i2c_detach_client(client); + + kfree(t); + kfree(client); + MOD_DEC_USE_COUNT; + return 0; +} + +static int tda7432_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct tda7432 *t = client->data; + d2printk("tda7432: In tda7432_command\n"); +#if 0 + __u16 *sarg = arg; +#endif + + switch (cmd) { + /* --- v4l ioctls --- */ + /* take care: bttv does userspace copying, we'll get a + kernel pointer here... */ + + /* Query card - scale from TDA7432 settings to V4L settings */ + case VIDIOCGAUDIO: + { + struct video_audio *va = arg; + dprintk("tda7432: VIDIOCGAUDIO\n"); + + va->flags |= VIDEO_AUDIO_VOLUME | + VIDEO_AUDIO_BASS | + VIDEO_AUDIO_TREBLE; + + /* Master volume control + * V4L volume is min 0, max 65535 + * TDA7432 Volume: + * Min (-79dB) is 0x6f + * Max (+20dB) is 0x07 + * (Mask out bit 7 of vol - it's for the loudness setting) + */ + + va->volume = ( 0x6f - (t->volume & 0x7F) ) * 630; + + /* Balance depends on L,R attenuation + * V4L balance is 0 to 65535, middle is 32768 + * TDA7432 attenuation: min (0dB) is 0, max (-37.5dB) is 0x1f + * to scale up to V4L numbers, mult by 1057 + * attenuation exists for lf, lr, rf, rr + * we use only lf and rf (front channels) + */ + + if ( (t->lf) < (t->rf) ) + /* right is attenuated, balance shifted left */ + va->balance = (32768 - 1057*(t->rf)); + else + /* left is attenuated, balance shifted right */ + va->balance = (32768 + 1057*(t->lf)); + + /* Bass/treble */ + va->bass = 32768; /* brain hurts... set to middle for now */ + va->treble = 32768; /* brain hurts... set to middle for now */ + + break; /* VIDIOCGAUDIO case */ + } + + /* Set card - scale from V4L settings to TDA7432 settings */ + case VIDIOCSAUDIO: + { + struct video_audio *va = arg; + dprintk("tda7432: VIDEOCSAUDIO\n"); + + t->volume = 0x6f - ( (va->volume)/630 ); + + if (loudness) /* Turn on the loudness bit */ + t->volume |= TDA7432_LD_ON; + + if (va->balance < 32768) { + /* shifted to left, attenuate right */ + t->rr = (32768 - va->balance)/1057; + t->rf = t->rr; + } + else { + /* shifted to right, attenuate left */ + t->lf = (va->balance - 32768)/1057; + t->lr = t->lf; + } + + /* t->tone = 0xff; */ /* Brain hurts - no tone control for now... */ + + tda7432_write(client,TDA7432_VL, t->volume); + /* tda7432_write(client,TDA7432_TN, t->tone); */ + tda7432_write(client,TDA7432_LF, t->lf); + tda7432_write(client,TDA7432_LR, t->lr); + tda7432_write(client,TDA7432_RF, t->rf); + tda7432_write(client,TDA7432_RR, t->rr); + + break; + + } /* end of VIDEOCSAUDIO case */ + + default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */ + + /* nothing */ + d2printk("tda7432: Default\n"); + + } /* end of (cmd) switch */ + + return 0; +} + + +static struct i2c_driver driver = { + "i2c tda7432 driver", + I2C_DRIVERID_TDA7432, + I2C_DF_NOTIFY, + tda7432_probe, + tda7432_detach, + tda7432_command, +}; + +static struct i2c_client client_template = +{ + "(unset)", /* name */ + -1, + 0, + 0, + NULL, + &driver +}; + +#ifdef MODULE +int init_module(void) +#else +int tda7432_init(void) +#endif +{ + + if ( (loudness < 0) || (loudness > 15) ) + { + printk(KERN_ERR "tda7432: loudness parameter must be between 0 and 15\n"); + return -EINVAL; + } + + + i2c_add_driver(&driver); + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + i2c_del_driver(&driver); +} +#endif + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/tda8425.c linux/drivers/char/tda8425.c --- v2.3.99-pre8/linux/drivers/char/tda8425.c Tue Jan 11 22:31:40 2000 +++ linux/drivers/char/tda8425.c Mon May 15 12:06:25 2000 @@ -31,7 +31,6 @@ #include "audiochip.h" /* Addresses to scan */ -#define I2C_TDA8425 0x82 static unsigned short normal_i2c[] = { I2C_TDA8425 >> 1, I2C_CLIENT_END}; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/tda985x.c linux/drivers/char/tda985x.c --- v2.3.99-pre8/linux/drivers/char/tda985x.c Tue Mar 7 14:32:25 2000 +++ linux/drivers/char/tda985x.c Mon May 15 12:06:25 2000 @@ -13,6 +13,7 @@ * * OPTIONS: * debug - set to 1 if you'd like to see debug messages + * - set to 2 if you'd like to be flooded with debug messages * chip - set to 9850 or 9855 to select your chip (default 9855) * * TODO: @@ -20,7 +21,8 @@ * and unmote to fix. - Is this still here? * Fine tune sound * Get rest of capabilities into video_audio struct... - * + * + * Revision 0.5 - cleaned up debugging messages, added debug level=2 * Revision: 0.4 - check for correct chip= insmod value * also cleaned up comments a bit * Revision: 0.3 - took out extraneous tda985x_write in tda985x_command @@ -55,9 +57,10 @@ #define I2C_TDA985x_H 0xb6 static unsigned short normal_i2c[] = {I2C_CLIENT_END}; static unsigned short normal_i2c_range[] = { - I2C_TDA985x_L >> 1, - I2C_TDA985x_H >> 1, - I2C_CLIENT_END}; + I2C_TDA985x_L >> 1, + I2C_TDA985x_H >> 1, + I2C_CLIENT_END +}; static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; @@ -84,6 +87,7 @@ static struct i2c_client client_template; #define dprintk if (debug) printk +#define d2printk if (debug == 2) printk /* The TDA9850 and TDA9855 are both made by Philips Semiconductor * http://www.semiconductors.philips.com @@ -154,9 +158,9 @@ #define TDA9855_AVL 1<<6 /* AVL, Automatic Volume Level */ #define TDA9855_LOUD 1<<5 /* Loudness, 1==off */ #define TDA9855_SUR 1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */ - /* Bits 0 to 3 select various combinations - * of line in and line out, only the - * interesting ones are defined */ + /* Bits 0 to 3 select various combinations + * of line in and line out, only the + * interesting ones are defined */ #define TDA9855_EXT 1<<2 /* Selects inputs LIR and LIL. Pins 41 & 12 */ #define TDA9855_INT 0 /* Selects inputs LOR and LOL. (internal) */ @@ -213,8 +217,8 @@ static int tda985x_write(struct i2c_client *client, int subaddr, int val) { unsigned char buffer[2]; - dprintk("In tda985x_write\n"); - dprintk("Writing %d 0x%x\n", subaddr, val); + d2printk("tda985x: In tda985x_write\n"); + dprintk("tda985x: Writing %d 0x%x\n", subaddr, val); buffer[0] = subaddr; buffer[1] = val; if (2 != i2c_master_send(client,buffer,2)) { @@ -228,12 +232,12 @@ static int tda985x_read(struct i2c_client *client) { unsigned char buffer; - dprintk("In tda985x_read\n"); + d2printk("tda985x: In tda985x_read\n"); if (1 != i2c_master_recv(client,&buffer,1)) { printk(KERN_WARNING "tda985x: I/O error, trying (read)\n"); return -1; } - dprintk("Read 0x%02x\n", buffer); + dprintk("tda985x: Read 0x%02x\n", buffer); return buffer; } @@ -241,12 +245,12 @@ { struct tda985x *t = client->data; unsigned char buf[16]; - dprintk("In tda985x_set\n"); + d2printk("tda985x: In tda985x_set\n"); if (chip == 9855) { dprintk(KERN_INFO - "tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", + "tda985x: tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", t->rvol,t->lvol,t->bass,t->treble,t->sub, t->c5,t->c6,t->c7,t->a1,t->a2,t->a3); buf[0] = TDA9855_VR; @@ -262,7 +266,7 @@ buf[10] = t->a2; buf[11] = t->a3; if (12 != i2c_master_send(client,buf,12)) { - printk(KERN_WARNING "tda9855: I/O error, trying tda985x_set\n"); + printk(KERN_WARNING "tda985x: I/O error, trying tda985x_set\n"); return -1; } } @@ -270,7 +274,7 @@ else if (chip == 9850) { dprintk(KERN_INFO - "tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", + "tda986x: tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", t->c4,t->c5,t->c6,t->c7,t->a1,t->a2,t->a3); buf[0] = TDA9850_C4; buf[1] = t->c4; @@ -281,7 +285,7 @@ buf[6] = t->a2; buf[7] = t->a3; if (8 != i2c_master_send(client,buf,8)) { - printk(KERN_WARNING "tda9850: I/O error, trying tda985x_set\n"); + printk(KERN_WARNING "tda985x: I/O error, trying tda985x_set\n"); return -1; } } @@ -292,11 +296,11 @@ static void do_tda985x_init(struct i2c_client *client) { struct tda985x *t = client->data; - dprintk("In tda985x_init\n"); + d2printk("tda985x: In tda985x_init\n"); if (chip == 9855) { - printk("Using tda9855 options\n"); + printk("tda985x: Using tda9855 options\n"); t->rvol = 0x6f; /* 0dB */ t->lvol = 0x6f; /* 0dB */ t->bass = 0x0e; /* 0dB */ @@ -313,7 +317,7 @@ else if (chip == 9850) { - printk("Using tda9850 options\n"); + printk("tda985x: Using tda9850 options\n"); t->c4 = 0x08; /* Set stereo noise thresh to nominal */ t->c5 = 0x08; /* Set SAP noise threshold to nominal */ t->c6 = TDA985x_STEREO; /* Select Stereo mode for decoder */ @@ -337,7 +341,7 @@ { struct tda985x *t; struct i2c_client *client; - dprintk("In tda985x_attach\n"); + d2printk("tda985x: In tda985x_attach\n"); client = kmalloc(sizeof *client,GFP_KERNEL); if (!client) return -ENOMEM; @@ -382,7 +386,7 @@ unsigned int cmd, void *arg) { struct tda985x *t = client->data; - dprintk("In tda985x_command...\n"); + d2printk("tda985x: In tda985x_command\n"); #if 0 __u16 *sarg = arg; #endif @@ -394,7 +398,7 @@ case VIDIOCGAUDIO: { struct video_audio *va = arg; - dprintk("VIDIOCGAUDIO\n"); + dprintk("tda985x: VIDIOCGAUDIO\n"); if (chip == 9855) { int left,right; @@ -430,7 +434,7 @@ case VIDIOCSAUDIO: { struct video_audio *va = arg; - dprintk("VIDEOCSAUDIO...\n"); + dprintk("tda985x: VIDEOCSAUDIO\n"); if (chip == 9855) { int left,right; @@ -453,17 +457,17 @@ switch (va->mode) { case VIDEO_SOUND_MONO: - dprintk("VIDEO_SOUND_MONO\n"); + dprintk("tda985x: VIDEO_SOUND_MONO\n"); t->c6= TDA985x_MONO | (t->c6 & 0x3f); tda985x_write(client,TDA985x_C6,t->c6); break; case VIDEO_SOUND_STEREO: - dprintk("VIDEO_SOUND_STEREO\n"); + dprintk("tda985x: VIDEO_SOUND_STEREO\n"); t->c6= TDA985x_STEREO | (t->c6 & 0x3f); tda985x_write(client,TDA985x_C6,t->c6); break; case VIDEO_SOUND_LANG1: - dprintk("VIDEO_SOUND_LANG1\n"); + dprintk("tda985x: VIDEO_SOUND_LANG1\n"); t->c6= TDA985x_SAP | (t->c6 & 0x3f); tda985x_write(client,TDA985x_C6,t->c6); break; @@ -476,7 +480,7 @@ default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */ /* nothing */ - dprintk("Default\n"); + d2printk("tda985x: Default\n"); } /* end of (cmd) switch */ diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/tda9875.c linux/drivers/char/tda9875.c --- v2.3.99-pre8/linux/drivers/char/tda9875.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/tda9875.c Mon May 15 12:06:25 2000 @@ -0,0 +1,371 @@ +/* + * For the TDA9875 chip + * (The TDA9875 is used on the Diamond DTV2000 french version + * Other cards probably use these chips as well.) + * This driver will not complain if used with any + * other i2c device with the same address. + * + * Copyright (c) 2000 Guillamue Delvit based on Gerd Knorr source and + * Eric Sandeen + * This code is placed under the terms of the GNU General Public License + * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) + * Which was based on tda8425.c by Greg Alexander (c) 1998 + * + * OPTIONS: + * debug - set to 1 if you'd like to see debug messages + * + * Revision: 0.1 - original version + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bttv.h" +#include "audiochip.h" + +/* This driver ID is brand new, so define it if it's not in i2c-id.h yet */ +#ifndef I2C_DRIVERID_TDA9875 + #define I2C_DRIVERID_TDA9875 28 +#endif + + +MODULE_PARM(debug,"i"); + +static int debug = 0; /* insmod parameter */ + +/* Addresses to scan */ +static unsigned short normal_i2c[] = { + I2C_TDA9875 >> 1, + I2C_CLIENT_END}; +static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; +static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static struct i2c_client_address_data addr_data = { + normal_i2c, normal_i2c_range, + probe, probe_range, + ignore, ignore_range, + force +}; + +/* This is a superset of the TDA9875 */ +struct tda9875 { + int mode; + int rvol, lvol; + int bass, treble; +}; + + +static struct i2c_driver driver; +static struct i2c_client client_template; + +#define dprintk if (debug) printk + +/* The TDA9875 is made by Philips Semiconductor + * http://www.semiconductors.philips.com + * TDA9875: I2C-bus controlled DSP audio processor, FM demodulator + * + */ + + /* subaddresses for TDA9875 */ +#define TDA9875_MUT 0x12 /*General mute (value --> 0b11001100*/ +#define TDA9875_CFG 0x01 /* Config register (value --> 0b00000000 */ +#define TDA9875_DACOS 0x13 /*DAC i/o select (ADC) 0b0000100*/ +#define TDA9875_LOSR 0x16 /*Line output select regirter 0b0100 0001*/ + +#define TDA9875_CH1V 0x0c /*Chanel 1 volume (mute)*/ +#define TDA9875_CH2V 0x0d /*Chanel 2 volume (mute)*/ +#define TDA9875_SC1 0x14 /*SCART 1 in (mono)*/ +#define TDA9875_SC2 0x15 /*SCART 2 in (mono)*/ + +#define TDA9875_ADCIS 0x17 /*ADC input select (mono) 0b0110 000*/ +#define TDA9875_AER 0x19 /*Audio effect (AVL+Pseudo) 0b0000 0110*/ +#define TDA9875_MCS 0x18 /*Main channel select (DAC) 0b0000100*/ +#define TDA9875_MVL 0x1a /* Main volume gauche */ +#define TDA9875_MVR 0x1b /* Main volume droite */ +#define TDA9875_MBA 0x1d /* Main Basse */ +#define TDA9875_MTR 0x1e /* Main treble */ +#define TDA9875_ACS 0x1f /* Auxilary channel select (FM) 0b0000000*/ +#define TDA9875_AVL 0x20 /* Auxilary volume gauche */ +#define TDA9875_AVR 0x21 /* Auxilary volume droite */ +#define TDA9875_ABA 0x22 /* Auxilary Basse */ +#define TDA9875_ATR 0x23 /* Auxilary treble */ + +#define TDA9875_MSR 0x02 /* Monitor select register */ +#define TDA9875_C1MSB 0x03 /* Carrier 1 (FM) frequency register MSB */ +#define TDA9875_C1MIB 0x04 /* Carrier 1 (FM) frequency register (16-8]b */ +#define TDA9875_C1LSB 0x05 /* Carrier 1 (FM) frequency register LSB */ +#define TDA9875_C2MSB 0x06 /* Carrier 2 (nicam) frequency register MSB */ +#define TDA9875_C2MIB 0x07 /* Carrier 2 (nicam) frequency register (16-8]b */ +#define TDA9875_C2LSB 0x08 /* Carrier 2 (nicam) frequency register LSB */ +#define TDA9875_DCR 0x09 /* Demodulateur configuration regirter*/ +#define TDA9875_DEEM 0x0a /* FM de-emphasis regirter*/ +#define TDA9875_FMAT 0x0b /* FM Matrix regirter*/ + +/* values */ +#define TDA9875_MUTE_ON 0xff /* general mute */ +#define TDA9875_MUTE_OFF 0xcc /* general no mute */ + + + +/* Begin code */ + +static int tda9875_write(struct i2c_client *client, int subaddr, int val) +{ + unsigned char buffer[2]; + dprintk("In tda9875_write\n"); + dprintk("Writing %d 0x%x\n", subaddr, val); + buffer[0] = subaddr; + buffer[1] = val; + if (2 != i2c_master_send(client,buffer,2)) { + printk(KERN_WARNING "tda9875: I/O error, trying (write %d 0x%x)\n", + subaddr, val); + return -1; + } + return 0; +} + +#if 0 +static int tda9875_read(struct i2c_client *client) +{ + unsigned char buffer; + dprintk("In tda9875_read\n"); + if (1 != i2c_master_recv(client,&buffer,1)) { + printk(KERN_WARNING "tda9875: I/O error, trying (read)\n"); + return -1; + } + dprintk("Read 0x%02x\n", buffer); + return buffer; +} +#endif + +static void tda9875_set(struct i2c_client *client) +{ + struct tda9875 *tda = client->data; + + dprintk(KERN_DEBUG "tda9875_set(%04x,%04x,%04x,%04x)\n",tda->lvol,tda->rvol,tda->bass,tda->treble); + tda9875_write(client, TDA9875_MVL, tda->lvol / 600 - 84); + tda9875_write(client, TDA9875_MVR, tda->rvol / 600 -84); + tda9875_write(client, TDA9875_MBA, tda->bass / 2340 -12); + tda9875_write(client, TDA9875_MTR, tda->treble / 2621 -12); +} + +static void do_tda9875_init(struct i2c_client *client) +{ + struct tda9875 *t = client->data; + dprintk("In tda9875_init\n"); + tda9875_write(client, TDA9875_CFG, 0xd0 ); /*reg de config 0 (reset)*/ + tda9875_write(client, TDA9875_MSR, 0x03 ); /* Monitor 0b00000XXX*/ + tda9875_write(client, TDA9875_C1MSB, 0x00 ); /*Car1(FM) MSB XMHz*/ + tda9875_write(client, TDA9875_C1MIB, 0x00 ); /*Car1(FM) MIB XMHz*/ + tda9875_write(client, TDA9875_C1LSB, 0x00 ); /*Car1(FM) LSB XMHz*/ + tda9875_write(client, TDA9875_C2MSB, 0x00 ); /*Car2(NICAM) MSB XMHz*/ + tda9875_write(client, TDA9875_C2MIB, 0x00 ); /*Car2(NICAM) MIB XMHz*/ + tda9875_write(client, TDA9875_C2LSB, 0x00 ); /*Car2(NICAM) LSB XMHz*/ + tda9875_write(client, TDA9875_DCR, 0x00 ); /*Demod config 0x00*/ + tda9875_write(client, TDA9875_DEEM, 0x44 ); /*DE-Emph 0b0100 0100*/ + tda9875_write(client, TDA9875_FMAT, 0x00 ); /*FM Matrix reg 0x00*/ + tda9875_write(client, TDA9875_SC1, 0x00 ); /* SCART 1 (SC1)*/ + tda9875_write(client, TDA9875_SC2, 0x01 ); /* SCART 2 (sc2)*/ + + tda9875_write(client, TDA9875_CH1V, 0x10 ); /* Chanel volume 1 mute*/ + tda9875_write(client, TDA9875_CH2V, 0x10 ); /* Chanel volume 2 mute */ + tda9875_write(client, TDA9875_DACOS, 0x02 ); /* sig DAC i/o(in:nicam)*/ + tda9875_write(client, TDA9875_ADCIS, 0x6f ); /* sig ADC input(in:mono)*/ + tda9875_write(client, TDA9875_LOSR, 0x00 ); /* line out (in:mono)*/ + tda9875_write(client, TDA9875_AER, 0x00 ); /*06 Effect (AVL+PSEUDO) */ + tda9875_write(client, TDA9875_MCS, 0x44 ); /* Main ch select (DAC) */ + tda9875_write(client, TDA9875_MVL, 0x03 ); /* Vol Main left 10dB */ + tda9875_write(client, TDA9875_MVR, 0x03 ); /* Vol Main right 10dB*/ + tda9875_write(client, TDA9875_MBA, 0x00 ); /* Main Bass Main 0dB*/ + tda9875_write(client, TDA9875_MTR, 0x00 ); /* Main Treble Main 0dB*/ + tda9875_write(client, TDA9875_ACS, 0x44 ); /* Aux chan select (dac)*/ + tda9875_write(client, TDA9875_AVL, 0x00 ); /* Vol Aux left 0dB*/ + tda9875_write(client, TDA9875_AVR, 0x00 ); /* Vol Aux right 0dB*/ + tda9875_write(client, TDA9875_ABA, 0x00 ); /* Aux Bass Main 0dB*/ + tda9875_write(client, TDA9875_ATR, 0x00 ); /* Aux Aigus Main 0dB*/ + + tda9875_write(client, TDA9875_MUT, 0xcc ); /* General mute */ + + t->mode=AUDIO_MUTE; + t->lvol=t->rvol =51000; /* 0dB */ + t->bass=30420; /* 0dB */ + t->treble=34073; /* 0dB */ + tda9875_set(client); + +} + + +/* *********************** * + * i2c interface functions * + * *********************** */ + +static int tda9875_attach(struct i2c_adapter *adap, int addr, + unsigned short flags, int kind) +{ + struct tda9875 *t; + struct i2c_client *client; + dprintk("In tda9875_attach\n"); + client = kmalloc(sizeof *client,GFP_KERNEL); + if (!client) + return -ENOMEM; + memcpy(client,&client_template,sizeof(struct i2c_client)); + client->adapter = adap; + client->addr = addr; + + client->data = t = kmalloc(sizeof *t,GFP_KERNEL); + if (!t) + return -ENOMEM; + memset(t,0,sizeof *t); + do_tda9875_init(client); + MOD_INC_USE_COUNT; + strcpy(client->name,"TDA9875"); + printk(KERN_INFO "tda9875: init\n"); + + i2c_attach_client(client); + return 0; +} + +static int tda9875_probe(struct i2c_adapter *adap) +{ + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + return i2c_probe(adap, &addr_data, tda9875_attach); + return 0; +} + +static int tda9875_detach(struct i2c_client *client) +{ + struct tda9875 *t = client->data; + + do_tda9875_init(client); + i2c_detach_client(client); + + kfree(t); + kfree(client); + MOD_DEC_USE_COUNT; + return 0; +} + +static int tda9875_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + struct tda9875 *t = client->data; + + dprintk("In tda9875_command...\n"); + + switch (cmd) { + /* --- v4l ioctls --- */ + /* take care: bttv does userspace copying, we'll get a + kernel pointer here... */ + case VIDIOCGAUDIO: + { + struct video_audio *va = arg; + int left,right; + + dprintk("VIDIOCGAUDIO\n"); + + va->flags |= VIDEO_AUDIO_VOLUME | + VIDEO_AUDIO_BASS | + VIDEO_AUDIO_TREBLE; + + /* min is -84 max is 24 */ + left = (t->lvol+85)*600; + right = (t->rvol+85)*600; + va->volume=MAX(left,right); + va->balance=(32768*MIN(left,right))/ + (va->volume ? va->volume : 1); + va->balance=(leftbalance) : va->balance; + va->bass = (t->bass+13)*2340; /* min -12 max +15 */ + va->treble = (t->treble+13)*2621;/* min -12 max +12 */ + + va->mode |= VIDEO_SOUND_MONO; + + + break; /* VIDIOCGAUDIO case */ + } + + case VIDIOCSAUDIO: + { + struct video_audio *va = arg; + int left,right; + + dprintk("VIDEOCSAUDIO...\n"); + left = (MIN(65536 - va->balance,32768) * + va->volume) / 32768; + right = (MIN(va->balance,32768) * + va->volume) / 32768; + t->lvol = left/600-84; + t->rvol = right/600-84; + t->bass = va->bass/2340-12; + t->treble = va->treble/2621-12; + tda9875_set(client); + + break; + + } /* end of VIDEOCSAUDIO case */ + + default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */ + + /* nothing */ + dprintk("Default\n"); + + } /* end of (cmd) switch */ + + return 0; +} + + +static struct i2c_driver driver = { + "i2c tda9875 driver", + I2C_DRIVERID_TDA9875, /* Get new one for TDA9875 */ + I2C_DF_NOTIFY, + tda9875_probe, + tda9875_detach, + tda9875_command, +}; + +static struct i2c_client client_template = +{ + "(unset)", /* name */ + -1, + 0, + 0, + NULL, + &driver +}; + +#ifdef MODULE +int init_module(void) +#else +int tda9875_init(void) +#endif +{ + i2c_add_driver(&driver); + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + i2c_del_driver(&driver); +} +#endif + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ + diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/tea6420.c linux/drivers/char/tea6420.c --- v2.3.99-pre8/linux/drivers/char/tea6420.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/char/tea6420.c Mon May 15 12:06:25 2000 @@ -0,0 +1,268 @@ +/* + * for the TEA6420 chip (only found on 3DFX (STB) TV/FM cards to the best + * of my knowledge) + * Copyright (C) 2000 Dave Stuart + * This code is placed under the terms of the GNU General Public License + * Code liberally copied from tea6300 by . . . + * + * Copyright (c) 1998 Greg Alexander + * This code is placed under the terms of the GNU General Public License + * Code liberally copied from msp3400.c, which is by Gerd Knorr + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bttv.h" +#include "audiochip.h" + + +/* Addresses to scan */ +#define I2C_TEA6420 0x98 +static unsigned short normal_i2c[] = { + I2C_TEA6420 >> 1, + I2C_CLIENT_END}; +static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; +static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static struct i2c_client_address_data addr_data = { + normal_i2c, normal_i2c_range, + probe, probe_range, + ignore, ignore_range, + force +}; + + +MODULE_PARM(debug,"i"); +static int debug = 0; /* insmod parameter */ + +#define dprintk if (debug) printk + + +struct tea6420 { + int mode; /* set to AUDIO_{OFF,TUNER,RADIO,EXTERN} */ + int stereo; +}; + +static struct i2c_driver driver; +static struct i2c_client client_template; + +#define TEA6420_S_SA 0x00 /* stereo A input */ +#define TEA6420_S_SB 0x01 /* stereo B */ +#define TEA6420_S_SC 0x02 /* stereo C */ +#define TEA6420_S_SD 0x03 /* stereo D */ +#define TEA6420_S_SE 0x04 /* stereo E */ +#define TEA6420_S_GMU 0x05 /* general mute */ + + +/* ******************************** * + * functions for talking to TEA6420 * + * ******************************** */ + +static int tea6420_write(struct i2c_client *client, int val) +{ + unsigned char buffer[2]; + int result; + +/* buffer[0] = addr; */ + buffer[0] = val; + result = i2c_master_send(client,buffer,1); + if (1 != result) { + printk(KERN_WARNING "tea6420: I/O error, trying (write +0x%x) result = %d\n", val, result); + return -1; + } + return 0; +} + + +static void do_tea6420_init(struct i2c_client *client) +{ + struct tea6420 *tea = client->data; + + tea->mode=AUDIO_OFF; + tea->stereo=1; + tea6420_write(client, TEA6420_S_GMU); /* mute */ +} + +static void tea6420_audio(struct i2c_client *client, int mode) +{ + struct tea6420 *tea = client->data; + + /* valid for AUDIO_TUNER, RADIO, EXTERN, OFF */ + dprintk(KERN_DEBUG "tea6420_audio:%d (T,R,E,I,O)\n",mode); + tea->mode=mode; + if (mode==AUDIO_OFF) { /* just mute it */ + tea6420_write(client, TEA6420_S_GMU); + return; + } + switch(mode) { + case AUDIO_TUNER: + tea6420_write(client, TEA6420_S_SA); + break; + case AUDIO_RADIO: + tea6420_write(client, TEA6420_S_SB); + break; + case AUDIO_EXTERN: + tea6420_write(client, TEA6420_S_SC); + break; + } +} + + +/* *********************** * + * i2c interface functions * + * *********************** */ + +static int tea6420_attach(struct i2c_adapter *adap, int addr, + unsigned short flags, int kind) +{ + struct tea6420 *tea; + struct i2c_client *client; + + client = kmalloc(sizeof *client,GFP_KERNEL); + if (!client) + return -ENOMEM; + memcpy(client,&client_template,sizeof(struct i2c_client)); + client->adapter = adap; + client->addr = addr; + + client->data = tea = kmalloc(sizeof *tea,GFP_KERNEL); + if (!tea) + return -ENOMEM; + memset(tea,0,sizeof *tea); + do_tea6420_init(client); + + MOD_INC_USE_COUNT; + strcpy(client->name,"TEA6420"); + printk(KERN_INFO "tea6420: initialized\n"); + + i2c_attach_client(client); + return 0; +} + +static int tea6420_probe(struct i2c_adapter *adap) +{ + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + return i2c_probe(adap, &addr_data, tea6420_attach); + return 0; +} + +static int tea6420_detach(struct i2c_client *client) +{ + struct tea6420 *tea = client->data; + + do_tea6420_init(client); + i2c_detach_client(client); + + kfree(tea); + kfree(client); + MOD_DEC_USE_COUNT; + return 0; +} + +static int +tea6420_command(struct i2c_client *client, unsigned int cmd, void *arg) +{ + __u16 *sarg = arg; + + switch (cmd) { + case AUDC_SET_RADIO: + tea6420_audio(client,AUDIO_RADIO); + break; + case AUDC_SET_INPUT: + tea6420_audio(client,*sarg); + break; + + /* --- v4l ioctls --- */ + /* take care: bttv does userspace copying, we'll get a + kernel pointer here... */ + case VIDIOCGAUDIO: + { + struct video_audio *va = arg; + + va->flags |= VIDEO_AUDIO_VOLUME | + VIDEO_AUDIO_BASS | + VIDEO_AUDIO_TREBLE; +/* va->volume=MAX(tea->left,tea->right); + va->balance=(32768*MIN(tea->left,tea->right))/ + (va->volume ? va->volume : 1); + va->balance=(tea->leftright)? + (65535-va->balance) : va->balance; + va->bass = tea->bass; + va->treble = tea->treble; +*/ break; + } + case VIDIOCSAUDIO: + { + +/* tea->left = (MIN(65536 - va->balance,32768) * + va->volume) / 32768; + tea->right = (MIN(va->balance,32768) * + va->volume) / 32768; + tea->bass = va->bass; + tea->treble = va->treble; + tea6420_set(client); +*/ break; + } + +default: + /* nothing */ + } + return 0; +} + +static struct i2c_driver driver = { + "i2c tea6420 driver", + I2C_DRIVERID_TEA6420, + I2C_DF_NOTIFY, + tea6420_probe, + tea6420_detach, + tea6420_command, +}; + +static struct i2c_client client_template = +{ + "(unset)", /* name */ + -1, + 0, + 0, + NULL, + &driver +}; + +#ifdef MODULE +int init_module(void) +#else +int tea6420_init(void) +#endif +{ + i2c_add_driver(&driver); + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + i2c_del_driver(&driver); +} +#endif + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.3.99-pre8/linux/drivers/char/tty_io.c Thu May 11 15:30:07 2000 +++ linux/drivers/char/tty_io.c Sat May 20 12:07:56 2000 @@ -146,8 +146,8 @@ extern int serial167_init(void); extern long serial167_console_init(void); #endif -#ifdef CONFIG_8xx -extern console_8xx_init(void); +#if (defined(CONFIG_8xx) || defined(CONFIG_8260)) +extern void console_8xx_init(void); extern int rs_8xx_init(void); #endif /* CONFIG_8xx */ #ifdef CONFIG_HWC @@ -2194,7 +2194,7 @@ con_init(); #endif #ifdef CONFIG_SERIAL_CONSOLE -#ifdef CONFIG_8xx +#if (defined(CONFIG_8xx) || defined(CONFIG_8260)) console_8xx_init(); #elif defined(CONFIG_SERIAL) serial_console_init(); @@ -2340,7 +2340,7 @@ #ifdef CONFIG_RIO rio_init(); #endif -#ifdef CONFIG_8xx +#if (defined(CONFIG_8xx) || defined(CONFIG_8260)) rs_8xx_init(); #endif /* CONFIG_8xx */ pty_init(); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/videodev.c linux/drivers/char/videodev.c --- v2.3.99-pre8/linux/drivers/char/videodev.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/char/videodev.c Mon May 22 09:50:53 2000 @@ -41,7 +41,6 @@ static struct video_device *video_device[VIDEO_NUM_DEVICES]; #ifdef CONFIG_VIDEO_BT848 -extern int init_bttv_cards(struct video_init *); extern int i2c_tuner_init(struct video_init *); #endif #ifdef CONFIG_VIDEO_BWQCAM @@ -59,9 +58,8 @@ static struct video_init video_init_list[]={ #ifdef CONFIG_VIDEO_BT848 - {"i2c-tuner", i2c_tuner_init}, - {"bttv", init_bttv_cards}, -#endif + {"i2c-tuner", i2c_tuner_init}, +#endif #ifdef CONFIG_VIDEO_BWQCAM {"bw-qcam", init_bw_qcams}, #endif diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/Config.in linux/drivers/ide/Config.in --- v2.3.99-pre8/linux/drivers/ide/Config.in Wed Apr 26 16:34:07 2000 +++ linux/drivers/ide/Config.in Sat May 20 11:15:44 2000 @@ -12,6 +12,15 @@ dep_tristate ' Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE dep_mbool ' Use multi-mode by default' CONFIG_IDEDISK_MULTI_MODE $CONFIG_BLK_DEV_IDEDISK + + define_bool CONFIG_BLK_DEV_IDEDISK_VENDOR n + dep_mbool ' Fujitsu Vendor Specific' CONFIG_BLK_DEV_IDEDISK_FUJITSU $CONFIG_BLK_DEV_IDEDISK_VENDOR + dep_mbool ' IBM Vendor Specific' CONFIG_BLK_DEV_IDEDISK_IBM $CONFIG_BLK_DEV_IDEDISK_VENDOR + dep_mbool ' Maxtor Vendor Specific' CONFIG_BLK_DEV_IDEDISK_MAXTOR $CONFIG_BLK_DEV_IDEDISK_VENDOR + dep_mbool ' Quantum Vendor Specific' CONFIG_BLK_DEV_IDEDISK_QUANTUM $CONFIG_BLK_DEV_IDEDISK_VENDOR + dep_mbool ' Seagate Vendor Specific' CONFIG_BLK_DEV_IDEDISK_SEAGATE $CONFIG_BLK_DEV_IDEDISK_VENDOR + dep_mbool ' Western Digital Vendor Specific' CONFIG_BLK_DEV_IDEDISK_WD $CONFIG_BLK_DEV_IDEDISK_VENDOR + dep_tristate ' PCMCIA IDE support' CONFIG_BLK_DEV_IDECS $CONFIG_BLK_DEV_IDE $CONFIG_PCMCIA dep_tristate ' Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE dep_tristate ' Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/aec62xx.c linux/drivers/ide/aec62xx.c --- v2.3.99-pre8/linux/drivers/ide/aec62xx.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/ide/aec62xx.c Mon May 15 11:03:48 2000 @@ -176,6 +176,7 @@ }; struct chipset_bus_clock_list_entry aec62xx_base [] = { +#ifdef CONFIG_BLK_DEV_IDEDMA { XFER_UDMA_4, 0x41, 0x04, 0x31, 0x05 }, { XFER_UDMA_3, 0x41, 0x03, 0x31, 0x04 }, { XFER_UDMA_2, 0x41, 0x02, 0x31, 0x03 }, @@ -185,7 +186,7 @@ { XFER_MW_DMA_2, 0x41, 0x00, 0x31, 0x00 }, { XFER_MW_DMA_1, 0x42, 0x00, 0x31, 0x00 }, { XFER_MW_DMA_0, 0x7a, 0x00, 0x0a, 0x00 }, - +#endif /* CONFIG_BLK_DEV_IDEDMA */ { XFER_PIO_4, 0x41, 0x00, 0x31, 0x00 }, { XFER_PIO_3, 0x43, 0x00, 0x33, 0x00 }, { XFER_PIO_2, 0x78, 0x00, 0x08, 0x00 }, @@ -202,18 +203,22 @@ static byte pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table) { + int bus_speed = system_bus_clock(); + for ( ; chipset_table->xfer_speed ; chipset_table++) if (chipset_table->xfer_speed == speed) { - return ((byte) ((1) ? chipset_table->chipset_settings_33 : chipset_table->chipset_settings_34)); + return ((byte) ((bus_speed <= 33) ? chipset_table->chipset_settings_33 : chipset_table->chipset_settings_34)); } return 0x00; } static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table) { + int bus_speed = system_bus_clock(); + for ( ; chipset_table->xfer_speed ; chipset_table++) if (chipset_table->xfer_speed == speed) { - return ((byte) ((1) ? chipset_table->ultra_settings_33 : chipset_table->ultra_settings_34)); + return ((byte) ((bus_speed <= 33) ? chipset_table->ultra_settings_33 : chipset_table->ultra_settings_34)); } return 0x00; } @@ -222,8 +227,6 @@ { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - byte unit = (drive->select.b.unit & 0x01); - int drive_number = ((hwif->channel ? 2 : 0) + unit); int err = 0; unsigned short d_conf = 0x0000; byte ultra = 0x00; @@ -236,18 +239,18 @@ __save_flags(flags); /* local CPU only */ __cli(); /* local CPU only */ - pci_read_config_word(dev, 0x40|(2*drive_number), &d_conf); + pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf); tmp0 = pci_bus_clock_list(speed, aec62xx_base); SPLIT_BYTE(tmp0,tmp1,tmp2); MAKE_WORD(d_conf,tmp1,tmp2); - pci_write_config_word(dev, 0x40|(2*drive_number), d_conf); + pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf); tmp1 = 0x00; tmp2 = 0x00; pci_read_config_byte(dev, 0x54, &ultra); - tmp1 = ((0x00 << (2*drive_number)) | (ultra & ~(3 << (2*drive_number)))); + tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn)))); ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base); - tmp2 = ((ultra_conf << (2*drive_number)) | (tmp1 & ~(3 << (2*drive_number)))); + tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn)))); pci_write_config_byte(dev, 0x54, tmp2); __restore_flags(flags); /* local CPU only */ @@ -261,7 +264,6 @@ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; byte unit = (drive->select.b.unit & 0x01); - int drive_number = ((hwif->channel ? 2 : 0) + unit); byte ultra_pci = hwif->channel ? 0x45 : 0x44; int err = 0; byte drive_conf = 0x00; @@ -269,15 +271,14 @@ byte ultra = 0x00; byte tmp1 = 0x00; byte tmp2 = 0x00; - unsigned long flags; __save_flags(flags); /* local CPU only */ __cli(); /* local CPU only */ - pci_read_config_byte(dev, 0x40|drive_number, &drive_conf); + pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf); drive_conf = pci_bus_clock_list(speed, aec62xx_base); - pci_write_config_byte(dev, 0x40|drive_number, drive_conf); + pci_write_config_byte(dev, 0x40|drive->dn, drive_conf); pci_read_config_byte(dev, ultra_pci, &ultra); tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit)))); @@ -286,10 +287,24 @@ pci_write_config_byte(dev, ultra_pci, tmp2); __restore_flags(flags); /* local CPU only */ + if (!drive->init_speed) + drive->init_speed = speed; + err = ide_config_drive_speed(drive, speed); + drive->current_speed = speed; return(err); } + +static int aec62xx_tune_chipset (ide_drive_t *drive, byte speed) +{ + if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) { + return ((int) aec6210_tune_chipset(drive, speed)); + } else { + return ((int) aec6260_tune_chipset(drive, speed)); + } +} + #ifdef CONFIG_BLK_DEV_IDEDMA static int config_aec6210_chipset_for_dma (ide_drive_t *drive, byte ultra) { @@ -524,7 +539,7 @@ { #ifdef CONFIG_AEC62XX_TUNING hwif->tuneproc = &aec62xx_tune_drive; - + hwif->speedproc = &aec62xx_tune_chipset; #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) hwif->dmaproc = &aec62xx_dmaproc; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/alim15x3.c linux/drivers/ide/alim15x3.c --- v2.3.99-pre8/linux/drivers/ide/alim15x3.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/ide/alim15x3.c Mon May 15 11:03:48 2000 @@ -333,6 +333,7 @@ err = ide_config_drive_speed(drive, speed); +#ifdef CONFIG_BLK_DEV_IDEDMA if (speed >= XFER_SW_DMA_0) { unsigned long dma_base = hwif->dma_base; @@ -353,6 +354,9 @@ pci_write_config_byte(dev, 0x4b, tmpbyte); } } +#endif /* CONFIG_BLK_DEV_IDEDMA */ + + drive->current_speed = speed; return (err); } @@ -399,6 +403,9 @@ (void) ali15x3_tune_chipset(drive, speed); + if (!drive->init_speed) + drive->init_speed = speed; + rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : ((id->dma_mword >> 8) & 7) ? ide_dma_on : @@ -629,7 +636,7 @@ * has 80-pin (from host view) */ pci_read_config_byte(dev, 0x4a, &tmpbyte); - ata66 = (!(tmpbyte & ata66mask)) ? 0 : 1; + ata66 = (!(tmpbyte & ata66mask)) ? 1 : 0; __restore_flags(flags); return(ata66); @@ -673,6 +680,7 @@ hwif->tuneproc = &ali15x3_tune_drive; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; + hwif->speedproc = &ali15x3_tune_chipset; #ifndef CONFIG_BLK_DEV_IDEDMA hwif->autodma = 0; return; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/amd7409.c linux/drivers/ide/amd7409.c --- v2.3.99-pre8/linux/drivers/ide/amd7409.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/ide/amd7409.c Mon May 15 11:03:48 2000 @@ -81,21 +81,22 @@ struct pci_dev *dev = hwif->pci_dev; int err = 0; byte unit = (drive->select.b.unit & 0x01); - int drive_number = ((HWIF(drive)->channel ? 2 : 0) + unit); +#ifdef CONFIG_BLK_DEV_IDEDMA unsigned long dma_base = hwif->dma_base; +#endif /* CONFIG_BLK_DEV_IDEDMA */ byte drive_pci = 0x00; byte drive_pci2 = 0x00; byte ultra_timing = 0x00; byte dma_pio_timing = 0x00; byte pio_timing = 0x00; - switch (drive_number) { + switch (drive->dn) { case 0: drive_pci = 0x53; drive_pci2 = 0x4b; break; case 1: drive_pci = 0x52; drive_pci2 = 0x4a; break; case 2: drive_pci = 0x51; drive_pci2 = 0x49; break; case 3: drive_pci = 0x50; drive_pci2 = 0x48; break; default: - return ((int) ide_dma_off_quietly); + return -1; } pci_read_config_byte(dev, drive_pci, &ultra_timing); @@ -109,7 +110,7 @@ ultra_timing &= ~0xC7; dma_pio_timing &= ~0xFF; - pio_timing &= ~(0x03 << drive_number); + pio_timing &= ~(0x03 << drive->dn); #ifdef DEBUG printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ", @@ -117,67 +118,74 @@ #endif switch(speed) { +#ifdef CONFIG_BLK_DEV_IDEDMA case XFER_UDMA_4: ultra_timing |= 0x45; dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive_number); + pio_timing |= (0x03 << drive->dn); break; case XFER_UDMA_3: ultra_timing |= 0x44; dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive_number); + pio_timing |= (0x03 << drive->dn); break; case XFER_UDMA_2: ultra_timing |= 0x40; dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive_number); + pio_timing |= (0x03 << drive->dn); break; case XFER_UDMA_1: ultra_timing |= 0x41; dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive_number); + pio_timing |= (0x03 << drive->dn); break; case XFER_UDMA_0: ultra_timing |= 0x42; dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive_number); + pio_timing |= (0x03 << drive->dn); break; case XFER_MW_DMA_2: dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive_number); + pio_timing |= (0x03 << drive->dn); break; case XFER_MW_DMA_1: dma_pio_timing |= 0x21; - pio_timing |= (0x03 << drive_number); + pio_timing |= (0x03 << drive->dn); break; case XFER_MW_DMA_0: dma_pio_timing |= 0x77; - pio_timing |= (0x03 << drive_number); + pio_timing |= (0x03 << drive->dn); break; +#endif /* CONFIG_BLK_DEV_IDEDMA */ case XFER_PIO_4: dma_pio_timing |= 0x20; - pio_timing |= (0x03 << drive_number); + pio_timing |= (0x03 << drive->dn); break; case XFER_PIO_3: dma_pio_timing |= 0x22; - pio_timing |= (0x03 << drive_number); + pio_timing |= (0x03 << drive->dn); break; case XFER_PIO_2: dma_pio_timing |= 0x42; - pio_timing |= (0x03 << drive_number); + pio_timing |= (0x03 << drive->dn); break; case XFER_PIO_1: dma_pio_timing |= 0x65; - pio_timing |= (0x03 << drive_number); + pio_timing |= (0x03 << drive->dn); break; case XFER_PIO_0: default: dma_pio_timing |= 0xA8; - pio_timing |= (0x03 << drive_number); + pio_timing |= (0x03 << drive->dn); break; } + if (!drive->init_speed) + drive->init_speed = speed; + +#ifdef CONFIG_BLK_DEV_IDEDMA pci_write_config_byte(dev, drive_pci, ultra_timing); +#endif /* CONFIG_BLK_DEV_IDEDMA */ pci_write_config_byte(dev, drive_pci2, dma_pio_timing); pci_write_config_byte(dev, 0x4c, pio_timing); @@ -186,12 +194,16 @@ ultra_timing, dma_pio_timing, pio_timing); #endif +#ifdef CONFIG_BLK_DEV_IDEDMA if (speed > XFER_PIO_4) { outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2); } else { outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); } +#endif /* CONFIG_BLK_DEV_IDEDMA */ + err = ide_config_drive_speed(drive, speed); + drive->current_speed = speed; return (err); } @@ -231,6 +243,7 @@ break; } (void) amd7409_tune_chipset(drive, speed); + drive->current_speed = speed; } static void amd7409_tune_drive (ide_drive_t *drive, byte pio) @@ -403,13 +416,14 @@ void __init ide_init_amd7409 (ide_hwif_t *hwif) { hwif->tuneproc = &amd7409_tune_drive; + hwif->speedproc = &amd7409_tune_chipset; #ifndef CONFIG_BLK_DEV_IDEDMA hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; hwif->autodma = 0; return; -#endif /* CONFIG_BLK_DEV_IDEDMA */ +#else if (hwif->dma_base) { hwif->dmaproc = &amd7409_dmaproc; @@ -419,6 +433,7 @@ hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; } +#endif /* CONFIG_BLK_DEV_IDEDMA */ } void ide_dmacapable_amd7409 (ide_hwif_t *hwif, unsigned long dmabase) diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/cmd64x.c linux/drivers/ide/cmd64x.c --- v2.3.99-pre8/linux/drivers/ide/cmd64x.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/ide/cmd64x.c Mon May 15 11:03:48 2000 @@ -344,9 +344,9 @@ (void) ide_config_drive_speed(drive, speed); } -#ifdef CONFIG_BLK_DEV_IDEDMA -static int tune_chipset_for_dma (ide_drive_t *drive, byte speed) +static int cmd64x_tune_chipset (ide_drive_t *drive, byte speed) { +#ifdef CONFIG_BLK_DEV_IDEDMA ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; byte unit = (drive->select.b.unit & 0x01); @@ -357,6 +357,8 @@ u8 regU = 0; u8 regD = 0; + if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) return 1; + (void) pci_read_config_byte(dev, pciD, ®D); (void) pci_read_config_byte(dev, pciU, ®U); regD &= ~(unit ? 0x40 : 0x20); @@ -378,17 +380,37 @@ case XFER_SW_DMA_2: regD |= (unit ? 0x40 : 0x10); break; case XFER_SW_DMA_1: regD |= (unit ? 0x80 : 0x20); break; case XFER_SW_DMA_0: regD |= (unit ? 0xC0 : 0x30); break; +#else + int err = 0; + + switch(speed) { +#endif /* CONFIG_BLK_DEV_IDEDMA */ + case XFER_PIO_4: cmd64x_tuneproc(drive, 4); break; + case XFER_PIO_3: cmd64x_tuneproc(drive, 3); break; + case XFER_PIO_2: cmd64x_tuneproc(drive, 2); break; + case XFER_PIO_1: cmd64x_tuneproc(drive, 1); break; + case XFER_PIO_0: cmd64x_tuneproc(drive, 0); break; + default: return 1; } +#ifdef CONFIG_BLK_DEV_IDEDMA (void) pci_write_config_byte(dev, pciU, regU); +#endif /* CONFIG_BLK_DEV_IDEDMA */ + err = ide_config_drive_speed(drive, speed); + + drive->current_speed = speed; + +#ifdef CONFIG_BLK_DEV_IDEDMA regD |= (unit ? 0x40 : 0x20); (void) pci_write_config_byte(dev, pciD, regD); +#endif /* CONFIG_BLK_DEV_IDEDMA */ return err; } +#ifdef CONFIG_BLK_DEV_IDEDMA static int config_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66) { struct hd_driveid *id = drive->id; @@ -450,12 +472,15 @@ set_pio = 1; } + if (!drive->init_speed) + drive->init_speed = speed; + config_chipset_for_pio(drive, set_pio); if (set_pio) return ((int) ide_dma_off_quietly); - if (tune_chipset_for_dma(drive, speed)) + if (cmd64x_tune_chipset(drive, speed)) return ((int) ide_dma_off); rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on : @@ -680,8 +705,9 @@ class_rev &= 0xff; hwif->tuneproc = &cmd64x_tuneproc; + hwif->speedproc = &cmd64x_tune_chipset; hwif->drives[0].autotune = 1; - hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; if (!hwif->dma_base) return; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/hd.c linux/drivers/ide/hd.c --- v2.3.99-pre8/linux/drivers/ide/hd.c Mon Mar 27 08:08:24 2000 +++ linux/drivers/ide/hd.c Sat May 20 23:31:02 2000 @@ -881,3 +881,12 @@ return 0; } +static int parse_hd_setup (char *line) { + int ints[6]; + + (void) get_options(line, ARRAY_SIZE(ints), ints); + hd_setup(NULL, ints); + + return 0; +} +__setup("hd=", parse_hd_setup); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/hpt34x.c linux/drivers/ide/hpt34x.c --- v2.3.99-pre8/linux/drivers/ide/hpt34x.c Mon Mar 27 08:08:24 2000 +++ linux/drivers/ide/hpt34x.c Mon May 15 11:03:48 2000 @@ -96,14 +96,13 @@ static void hpt34x_clear_chipset (ide_drive_t *drive) { - int drive_number = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); unsigned int reg1 = 0, tmp1 = 0; unsigned int reg2 = 0, tmp2 = 0; pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, ®1); pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, ®2); - tmp1 = ((0x00 << (3*drive_number)) | (reg1 & ~(7 << (3*drive_number)))); - tmp2 = (reg2 & ~(0x11 << drive_number)); + tmp1 = ((0x00 << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn)))); + tmp2 = (reg2 & ~(0x11 << drive->dn)); pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1); pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2); } @@ -112,7 +111,6 @@ { int err; byte hi_speed, lo_speed; - int drive_number = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); unsigned int reg1 = 0, tmp1 = 0; unsigned int reg2 = 0, tmp2 = 0; @@ -127,20 +125,24 @@ pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, ®1); pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, ®2); - tmp1 = ((lo_speed << (3*drive_number)) | (reg1 & ~(7 << (3*drive_number)))); - tmp2 = ((hi_speed << drive_number) | reg2); + tmp1 = ((lo_speed << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn)))); + tmp2 = ((hi_speed << drive->dn) | reg2); err = ide_config_drive_speed(drive, speed); pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1); pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2); + if (!drive->init_speed) + drive->init_speed = speed; + #if HPT343_DEBUG_DRIVE_INFO printk("%s: %s drive%d (0x%04x 0x%04x) (0x%04x 0x%04x)" \ " (0x%02x 0x%02x) 0x%04x\n", drive->name, ide_xfer_verbose(speed), - drive_number, reg1, tmp1, reg2, tmp2, + drive->dn, reg1, tmp1, reg2, tmp2, hi_speed, lo_speed, err); #endif /* HPT343_DEBUG_DRIVE_INFO */ + drive->current_speed = speed; return(err); } @@ -410,6 +412,7 @@ void __init ide_init_hpt34x (ide_hwif_t *hwif) { hwif->tuneproc = &hpt34x_tune_drive; + hwif->speedproc = &hpt34x_tune_chipset; #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/hpt366.c linux/drivers/ide/hpt366.c --- v2.3.99-pre8/linux/drivers/ide/hpt366.c Mon Mar 27 08:08:24 2000 +++ linux/drivers/ide/hpt366.c Mon May 15 11:03:48 2000 @@ -173,6 +173,14 @@ byte hpt363_shared_irq = 0; byte hpt363_shared_pin = 0; +static unsigned int pci_rev_check_hpt366 (struct pci_dev *dev) +{ + unsigned int class_rev; + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + return ((int) (class_rev == 0x03) ? 1 : 0); +} + static int check_in_drive_lists (ide_drive_t *drive, const char **list) { struct hd_driveid *id = drive->id; @@ -212,9 +220,6 @@ static int hpt366_tune_chipset (ide_drive_t *drive, byte speed) { int err; -#if HPT366_DEBUG_DRIVE_INFO - int drive_number = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); -#endif /* HPT366_DEBUG_DRIVE_INFO */ byte regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40; unsigned int reg1 = 0; unsigned int reg2 = 0; @@ -251,11 +256,15 @@ pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2); err = ide_config_drive_speed(drive, speed); + if (!drive->init_speed) + drive->init_speed = speed; + #if HPT366_DEBUG_DRIVE_INFO printk("%s: speed=0x%02x(%s), drive%d, old=0x%08x, new=0x%08x, err=0x%04x\n", drive->name, speed, ide_xfer_verbose(speed), - drive_number, reg1, reg2, err); + drive->dn, reg1, reg2, err); #endif /* HPT366_DEBUG_DRIVE_INFO */ + drive->current_speed = speed; return(err); } @@ -469,10 +478,12 @@ case ide_dma_check: return config_drive_xfer_rate(drive); case ide_dma_lostirq: +#if 0 pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, ®50h); pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h|0x03); pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, ®50h); /* ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); */ +#endif case ide_dma_timeout: default: break; @@ -508,6 +519,8 @@ if (!hpt366_proc) { hpt366_proc = 1; bmide_dev = dev; + if (pci_rev_check_hpt366(dev)) + bmide2_dev = dev; hpt366_display_info = &hpt366_get_info; } if ((hpt366_proc) && ((dev->devfn - bmide_dev->devfn) == 1)) { @@ -533,7 +546,11 @@ void __init ide_init_hpt366 (ide_hwif_t *hwif) { + if (pci_rev_check_hpt366(hwif->pci_dev)) return; + hwif->tuneproc = &hpt366_tune_drive; + hwif->speedproc = &hpt366_tune_chipset; + #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { hwif->dmaproc = &hpt366_dmaproc; @@ -555,6 +572,11 @@ byte masterdma = 0, slavedma = 0; byte dma_new = 0, dma_old = inb(dmabase+2); unsigned long flags; + + if (pci_rev_check_hpt366(hwif->pci_dev)) { + ide_setup_dma(hwif, dmabase, 8); + return; + } __save_flags(flags); /* local CPU only */ __cli(); /* local CPU only */ diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/icside.c linux/drivers/ide/icside.c --- v2.3.99-pre8/linux/drivers/ide/icside.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/ide/icside.c Mon May 15 12:03:25 2000 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -219,55 +220,73 @@ * here, but we rely on the main IDE driver spotting that both * interfaces use the same IRQ, which should guarantee this. */ -#define TABLE_SIZE 2048 +#define NR_ENTRIES 256 +#define TABLE_SIZE (NR_ENTRIES * 8) -static int -icside_build_dmatable(ide_drive_t *drive, int reading) +static int ide_build_sglist(ide_hwif_t *hwif, struct request *rq) { - struct request *rq = HWGROUP(drive)->rq; - struct buffer_head *bh = rq->bh; - unsigned long addr, size; - unsigned char *virt_addr; - unsigned int count = 0; - dmasg_t *sg = (dmasg_t *)HWIF(drive)->dmatable_cpu; + struct buffer_head *bh; + struct scatterlist *sg = hwif->sg_table; + int nents = 0; + if (rq->cmd == READ) + hwif->sg_dma_direction = PCI_DMA_FROMDEVICE; + else + hwif->sg_dma_direction = PCI_DMA_TODEVICE; + bh = rq->bh; do { - if (bh == NULL) { - /* paging requests have (rq->bh == NULL) */ - virt_addr = rq->buffer; - addr = virt_to_bus (virt_addr); - size = rq->nr_sectors << 9; - } else { - /* group sequential buffers into one large buffer */ - virt_addr = bh->b_data; - addr = virt_to_bus (virt_addr); - size = bh->b_size; - while ((bh = bh->b_reqnext) != NULL) { - if ((addr + size) != virt_to_bus (bh->b_data)) - break; - size += bh->b_size; - } - } + unsigned char *virt_addr = bh->b_data; + unsigned int size = bh->b_size; - if (addr & 3) { - printk("%s: misaligned DMA buffer\n", drive->name); - return 0; + while ((bh = bh->b_reqnext) != NULL) { + if ((virt_addr + size) != (unsigned char *)bh->b_data) + break; + size += bh->b_size; } + memset(&sg[nents], 0, sizeof(*sg)); + sg[nents].address = virt_addr; + sg[nents].length = size; + nents++; + } while (bh != NULL); - if (size) { - if (reading) - dma_cache_inv((unsigned int)virt_addr, size); - else - dma_cache_wback((unsigned int)virt_addr, size); - } + return pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction); +} + +static int +icside_build_dmatable(ide_drive_t *drive, int reading) +{ + dmasg_t *ide_sg = (dmasg_t *)HWIF(drive)->dmatable_cpu; + unsigned int count = 0; + int i; + struct scatterlist *sg; + + HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq); - sg[count].address = addr; - sg[count].length = size; - if (++count >= (TABLE_SIZE / sizeof(dmasg_t))) { - printk("%s: DMA table too small\n", drive->name); + sg = HWIF(drive)->sg_table; + while (i && sg_dma_len(sg)) { + u32 cur_addr; + u32 cur_len; + + cur_addr = sg_dma_address(sg); + cur_len = sg_dma_len(sg); + + if (count >= (TABLE_SIZE / sizeof(dmasg_t))) { + printk("%s: DMA table too small\n", + drive->name); + pci_unmap_sg(NULL, + HWIF(drive)->sg_table, + HWIF(drive)->sg_nents, + HWIF(drive)->sg_dma_direction); return 0; + } else { + ide_sg[count].address = cur_addr; + ide_sg[count].length = cur_len; } - } while (bh != NULL); + + count++; + sg++; + i--; + } if (!count) printk("%s: empty DMA table?\n", drive->name); @@ -275,6 +294,15 @@ return count; } +/* Teardown mappings after DMA has completed. */ +static void icside_destroy_dmatable(ide_drive_t *drive) +{ + struct scatterlist *sg = HWIF(drive)->sg_table; + int nents = HWIF(drive)->sg_nents; + + pci_unmap_sg(NULL, sg, nents, HWIF(drive)->sg_dma_direction); +} + static int icside_config_if(ide_drive_t *drive, int xfer_mode) { @@ -303,6 +331,9 @@ break; } + if (!drive->init_speed) + drive->init_speed = (byte) xfer_mode; + if (drive->drive_data && ide_config_drive_speed(drive, (byte) xfer_mode) == 0) func = ide_dma_on; @@ -312,10 +343,18 @@ printk("%s: %s selected (peak %dMB/s)\n", drive->name, ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data); + drive->current_speed = (byte) xfer_mode; + return func; } static int +icside_set_speed(ide_drive_t *drive, byte speed) +{ + return ((int) icside_config_if(drive, (int) speed)); +} + +static int icside_dma_check(ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -415,6 +454,7 @@ case ide_dma_end: drive->waiting_for_dma = 0; disable_dma(hwif->hw.dma); + icside_destroy_dmatable(drive); return get_dma_residue(hwif->hw.dma) != 0; case ide_dma_test_irq: @@ -425,8 +465,7 @@ } } -static unsigned long -icside_alloc_dmatable(void) +static void *icside_alloc_dmatable(void) { static unsigned long dmatable; static unsigned int leftover; @@ -448,28 +487,39 @@ leftover -= TABLE_SIZE; } - return table; + return (void *)table; } static int icside_setup_dma(ide_hwif_t *hwif, int autodma) { - unsigned long table = icside_alloc_dmatable(); - printk(" %s: SG-DMA", hwif->name); - if (!table) - printk(" -- ERROR, unable to allocate DMA table\n"); - else { - hwif->dmatable_cpu = (void *)table; - hwif->dmaproc = icside_dmaproc; - hwif->autodma = autodma; - - printk(" capable%s\n", autodma ? - ", auto-enable" : ""); + hwif->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES, + GFP_KERNEL); + if (!hwif->sg_table) + goto failed; + + hwif->dmatable_cpu = icside_alloc_dmatable(); + + if (!hwif->dmatable_cpu) { + kfree(hwif->sg_table); + hwif->sg_table = NULL; + goto failed; } - return hwif->dmatable_cpu != NULL; + hwif->dmaproc = &icside_dmaproc; + hwif->autodma = autodma; + hwif->speedproc = &icside_set_speed; + + printk(" capable%s\n", autodma ? + ", auto-enable" : ""); + + return 1; + +failed: + printk(" -- ERROR, unable to allocate DMA table\n"); + return 0; } #endif diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c --- v2.3.99-pre8/linux/drivers/ide/ide-disk.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/ide/ide-disk.c Mon May 15 11:03:48 2000 @@ -33,8 +33,6 @@ #undef REALLY_SLOW_IO /* most systems can safely undef this */ -#define _IDE_DISK_C /* Tell linux/hdsmart.h it's really us */ - #include #include #include @@ -688,13 +686,12 @@ static int set_nowerr(ide_drive_t *drive, int arg) { - unsigned long flags; - - if (ide_spin_wait_hwgroup(drive, &flags)) + if (ide_spin_wait_hwgroup(drive)) return -EBUSY; + drive->nowerr = arg; drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT; - spin_unlock_irqrestore(&io_request_lock, flags); + spin_unlock_irq(&io_request_lock); return 0; } @@ -713,7 +710,7 @@ ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL); ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL); ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL); - + ide_add_setting(drive, "lun", SETTING_RW, -1, -1, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL); } /* diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/ide-features.c linux/drivers/ide/ide-features.c --- v2.3.99-pre8/linux/drivers/ide/ide-features.c Mon Mar 27 08:08:24 2000 +++ linux/drivers/ide/ide-features.c Mon May 15 11:03:48 2000 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -109,6 +110,46 @@ } /* + * + */ +byte ide_auto_reduce_xfer (ide_drive_t *drive) +{ + switch(drive->current_speed) { + case XFER_UDMA_7: return XFER_UDMA_6; + case XFER_UDMA_6: return XFER_UDMA_5; + case XFER_UDMA_5: return XFER_UDMA_4; + case XFER_UDMA_4: return XFER_UDMA_3; + case XFER_UDMA_3: return XFER_UDMA_2; + case XFER_UDMA_2: return XFER_UDMA_1; + case XFER_UDMA_1: return XFER_UDMA_0; + case XFER_UDMA_0: + if (drive->id->dma_mword & 0x0004) return XFER_MW_DMA_2; + else if (drive->id->dma_mword & 0x0002) return XFER_MW_DMA_1; + else if (drive->id->dma_mword & 0x0001) return XFER_MW_DMA_0; + else return XFER_PIO_4; + case XFER_MW_DMA_2: return XFER_MW_DMA_1; + case XFER_MW_DMA_1: return XFER_MW_DMA_0; + case XFER_MW_DMA_0: + if (drive->id->dma_1word & 0x0004) return XFER_SW_DMA_2; + else if (drive->id->dma_1word & 0x0002) return XFER_SW_DMA_1; + else if (drive->id->dma_1word & 0x0001) return XFER_SW_DMA_0; + else return XFER_PIO_4; + case XFER_SW_DMA_2: return XFER_SW_DMA_1; + case XFER_SW_DMA_1: return XFER_SW_DMA_0; + case XFER_SW_DMA_0: + { + return XFER_PIO_4; + } + case XFER_PIO_4: return XFER_PIO_3; + case XFER_PIO_3: return XFER_PIO_2; + case XFER_PIO_2: return XFER_PIO_1; + case XFER_PIO_1: return XFER_PIO_0; + case XFER_PIO_0: + default: return XFER_PIO_SLOW; + } +} + +/* * Update the */ int ide_driveid_update (ide_drive_t *drive) @@ -136,8 +177,10 @@ ide_delay_50ms(); /* give drive a breather */ } while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT); ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */ - if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) + if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) { + printk("%s: CHECK for good STATUS\n", drive->name); return 0; + } __save_flags(flags); /* local CPU only */ __cli(); /* local CPU only; some systems need this */ id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC); @@ -146,17 +189,14 @@ ide__sti(); /* local CPU only */ __restore_flags(flags); /* local CPU only */ ide_fix_driveid(id); - if (id && id->cyls) { + if (id) { drive->id->dma_ultra = id->dma_ultra; drive->id->dma_mword = id->dma_mword; drive->id->dma_1word = id->dma_1word; /* anything more ? */ -#ifdef DEBUG - printk("%s: dma_ultra=%04X, dma_mword=%04X, dma_1word=%04X\n", - drive->name, id->dma_ultra, id->dma_mword, id->dma_1word); -#endif kfree(id); } + return 1; } @@ -167,7 +207,7 @@ * in combination with the device (usually a disk) properly detect * and acknowledge each end of the ribbon. */ -int ide_ata66_check (ide_drive_t *drive, int cmd, int nsect, int feature) +int ide_ata66_check (ide_drive_t *drive, byte cmd, byte nsect, byte feature) { if ((cmd == WIN_SETFEATURES) && (nsect > XFER_UDMA_2) && @@ -189,15 +229,16 @@ * 1 : Safe to update drive->id DMA registers. * 0 : OOPs not allowed. */ -int set_transfer (ide_drive_t *drive, int cmd, int nsect, int feature) +int set_transfer (ide_drive_t *drive, byte cmd, byte nsect, byte feature) { - struct hd_driveid *id = drive->id; - if ((cmd == WIN_SETFEATURES) && (nsect >= XFER_SW_DMA_0) && (feature == SETFEATURES_XFER) && - (id->dma_ultra || id->dma_mword || id->dma_1word)) + (drive->id->dma_ultra || + drive->id->dma_mword || + drive->id->dma_1word)) return 1; + return 0; } @@ -219,6 +260,8 @@ byte unit = (drive->select.b.unit & 0x01); byte stat; + outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2); + /* * Don't use ide_wait_cmd here - it will * attempt to set_geometry and recalibrate, @@ -307,6 +350,7 @@ return error; } +EXPORT_SYMBOL(ide_auto_reduce_xfer); EXPORT_SYMBOL(ide_driveid_update); EXPORT_SYMBOL(ide_ata66_check); EXPORT_SYMBOL(set_transfer); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/ide-pci.c linux/drivers/ide/ide-pci.c --- v2.3.99-pre8/linux/drivers/ide/ide-pci.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/ide/ide-pci.c Mon May 15 11:03:48 2000 @@ -30,6 +30,7 @@ #define DEVID_PIIX3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1}) #define DEVID_PIIX4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB}) #define DEVID_PIIX4E ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1}) +#define DEVID_PIIX4E2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1}) #define DEVID_PIIX4U ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1}) #define DEVID_PIIX4U2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1}) #define DEVID_VIA_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561}) @@ -303,6 +304,7 @@ {DEVID_PIIX3, "PIIX3", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_PIIX4, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_PIIX4E, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_PIIX4E2, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_PIIX4U, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_PIIX4U2, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, @@ -476,6 +478,7 @@ unsigned short pcicmd = 0, tried_config = 0; byte tmp = 0; ide_hwif_t *hwif, *mate = NULL; + unsigned int class_rev; #ifdef CONFIG_IDEDMA_AUTO autodma = 1; @@ -504,6 +507,11 @@ } if (tried_config) printk("%s: device enabled (Linux)\n", d->name); + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + printk("%s: chipset revision %d\n", d->name, class_rev); + /* * Can we trust the reported IRQ? */ @@ -545,7 +553,7 @@ ide_pci_enablebit_t *e = &(d->enablebits[port]); if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val)) continue; /* port not enabled */ - if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port)) + if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port) && (class_rev != 0x03)) return; if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) { ctl = dev->resource[(2*port)+1].start; @@ -656,9 +664,19 @@ struct pci_dev *dev2 = NULL, *findev; ide_pci_device_t *d2; unsigned char pin1 = 0, pin2 = 0; + unsigned int class_rev; if (PCI_FUNC(dev->devfn) & 1) return; + + pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); + class_rev &= 0xff; + + switch(class_rev) { + case 3: return; + default: break; + } + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1); pci_for_each_dev(findev) { if ((findev->vendor == dev->vendor) && diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/ide-pmac.c linux/drivers/ide/ide-pmac.c --- v2.3.99-pre8/linux/drivers/ide/ide-pmac.c Mon Mar 27 08:08:24 2000 +++ linux/drivers/ide/ide-pmac.c Mon May 15 11:03:48 2000 @@ -7,6 +7,8 @@ * * Copyright (C) 1998 Paul Mackerras. * + * Bits from Benjamin Herrenschmidt + * * 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 @@ -16,12 +18,6 @@ * * Copyright (c) 1995-1998 Mark Lord * - * BenH: I began adding more complete timing setup code, mostly because DMA - * won't work on new machines unless timings are setup correctly. This - * code was mainly stolen from Cmd646 driver and should be completed to - * include real timing calc. instead of hard coded values. The format of - * the timing register can be found in Darwin's source code, except for - * Keylargo ATA-4 controller. */ #include #include @@ -44,14 +40,18 @@ #endif #include "ide_modes.h" +extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc); + #undef IDE_PMAC_DEBUG -#define IDE_SYSCLK_NS 30 +#define IDE_SYSCLK_NS 30 +#define IDE_SYSCLK_ULTRA_PS 0x1d4c /* (15 * 1000 / 2)*/ struct pmac_ide_hwif { ide_ioreg_t regbase; int irq; int kind; + int aapl_bus_id; struct device_node* node; u32 timings[2]; #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC @@ -90,17 +90,27 @@ static pmac_ide_timing udma_timings[] = { { 0, 114 }, /* Mode 0 */ - { 0, 73 }, /* 1 */ - { 0, 54 }, /* 2 */ - { 0, 39 }, /* 3 */ - { 0, 25 } /* 4 */ + { 0, 75 }, /* 1 */ + { 0, 55 }, /* 2 */ + { 100, 45 }, /* 3 */ + { 100, 25 } /* 4 */ }; -#define MAX_DCMDS 256 /* allow up to 256 DBDMA commands per xfer */ +/* allow up to 256 DBDMA commands per xfer */ +#define MAX_DCMDS 256 + +/* Wait 1.5s for disk to answer on IDE bus after + * enable operation. + * NOTE: There is at least one case I know of a disk that needs about 10sec + * before anwering on the bus. I beleive we could add a kernel command + * line arg to override this delay for such cases. + */ +#define IDE_WAKEUP_DELAY_MS 1500 static void pmac_ide_setup_dma(struct device_node *np, int ix); static int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive); static int pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr); +static int pmac_ide_tune_chipset(ide_drive_t *drive, byte speed); static void pmac_ide_tuneproc(ide_drive_t *drive, byte pio); static void pmac_ide_selectproc(ide_drive_t *drive); @@ -156,14 +166,6 @@ return; } - /* we check only for -EINVAL meaning that we have found a matching - bay but with the wrong device type */ - i = check_media_bay_by_base(data_port, MB_CD); - if (i == -EINVAL) { - hw->io_ports[IDE_DATA_OFFSET] = 0; - return; - } - for (i = 0; i < 8; ++i) hw->io_ports[i] = data_port + i * 0x10; hw->io_ports[8] = data_port + 0x160; @@ -178,6 +180,7 @@ #ifdef CONFIG_PMAC_IDEDMA_AUTO ide_hwifs[ix].autodma = 1; #endif +// ide_hwifs[ix].speedproc = &pmac_ide_tune_chipset; } } @@ -214,7 +217,9 @@ /* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */ #define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS) +#define SYSCLK_TICKS_UDMA(t) (((t) + IDE_SYSCLK_ULTRA_PS - 1) / IDE_SYSCLK_ULTRA_PS) +/* Calculate PIO timings */ static void pmac_ide_tuneproc(ide_drive_t *drive, byte pio) { @@ -227,26 +232,31 @@ if (i < 0) return; - /* The "ata-4" IDE controller of UMA machines is a bit different. - * We don't do anything for PIO modes until we know how to do the - * calculation. - */ - if (pmac_ide[i].kind == controller_kl_ata4) - return; - pio = ide_get_best_pio_mode(drive, pio, 4, &d); accessTicks = SYSCLK_TICKS(ide_pio_timings[pio].active_time); - if (accessTicks < 4) - accessTicks = 4; - recTicks = SYSCLK_TICKS(d.cycle_time) - accessTicks - 4; - if (recTicks < 1) - recTicks = 1; if (drive->select.all & 0x10) timings = &pmac_ide[i].timings[1]; else timings = &pmac_ide[i].timings[0]; - *timings = ((*timings) & 0xFFFFFF800) | accessTicks | (recTicks << 5); + if (pmac_ide[i].kind == controller_kl_ata4) { + /* The "ata-4" IDE controller of Core99 machines */ + accessTicks = SYSCLK_TICKS_UDMA(ide_pio_timings[pio].active_time * 1000); + recTicks = SYSCLK_TICKS_UDMA(d.cycle_time * 1000) - accessTicks; + + *timings = ((*timings) & 0x1FFFFFC00) | accessTicks | (recTicks << 5); + } else { + /* The old "ata-3" IDE controller */ + accessTicks = SYSCLK_TICKS(ide_pio_timings[pio].active_time); + if (accessTicks < 4) + accessTicks = 4; + recTicks = SYSCLK_TICKS(d.cycle_time) - accessTicks - 4; + if (recTicks < 1) + recTicks = 1; + + *timings = ((*timings) & 0xFFFFFF800) | accessTicks | (recTicks << 5); + } + #ifdef IDE_PMAC_DEBUG printk("ide_pmac: Set PIO timing for mode %d, reg: 0x%08x\n", pio, *timings); @@ -294,7 +304,7 @@ struct device_node *atas; struct device_node *p, **pp, *removables, **rp; unsigned long base; - int irq; + int irq, big_delay; ide_hwif_t *hwif; if (_machine != _MACH_Pmac) @@ -322,9 +332,11 @@ } *rp = NULL; *pp = removables; + big_delay = 0; for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) { struct device_node *tp; + int *bidp; /* * If this node is not under a mac-io or dbdma node, @@ -378,6 +390,9 @@ else pmac_ide[i].kind = controller_ohare; + bidp = (int *)get_property(np, "AAPL,bus-id", NULL); + pmac_ide[i].aapl_bus_id = bidp ? *bidp : 0; + if (np->parent && np->parent->name && strcasecmp(np->parent->name, "media-bay") == 0) { media_bay_set_ide_infos(np->parent,base,irq,i); @@ -388,42 +403,41 @@ */ feature_set(np, FEATURE_IDE0_enable); } else { - /* This is necessary to enable IDE when net-booting */ - int *bidp = (int *)get_property(np, "AAPL,bus-id", NULL); - int bid = bidp ? *bidp : 0; - printk("pmac_ide: enabling IDE bus ID %d\n", bid); - switch(bid) { + /* This is necessary to enable IDE when net-booting */ + printk("pmac_ide: enabling IDE bus ID %d\n", + pmac_ide[i].aapl_bus_id); + switch(pmac_ide[i].aapl_bus_id) { case 0: feature_set(np, FEATURE_IDE0_reset); - feature_set(np, FEATURE_IOBUS_enable); mdelay(10); feature_set(np, FEATURE_IDE0_enable); mdelay(10); feature_clear(np, FEATURE_IDE0_reset); break; case 1: - feature_set(np, FEATURE_Mediabay_IDE_reset); + feature_set(np, FEATURE_IDE1_reset); mdelay(10); - feature_set(np, FEATURE_Mediabay_IDE_enable); + feature_set(np, FEATURE_IDE1_enable); mdelay(10); - feature_clear(np, FEATURE_Mediabay_IDE_reset); + feature_clear(np, FEATURE_IDE1_reset); break; case 2: - /* This one exists only for KL, I don't know about any - enable bit */ + /* This one exists only for KL, I don't know + about any enable bit */ feature_set(np, FEATURE_IDE2_reset); mdelay(10); feature_clear(np, FEATURE_IDE2_reset); break; } - mdelay(1000); + big_delay = 1; } hwif = &ide_hwifs[i]; pmac_ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->irq); memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports)); hwif->chipset = ide_pmac; - hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; + hwif->noprobe = (!hwif->io_ports[IDE_DATA_OFFSET]) || + (check_media_bay_by_base(base, MB_CD) == -EINVAL); #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC if (np->n_addrs >= 2) { @@ -435,6 +449,8 @@ ++i; } pmac_ide_count = i; + if (big_delay) + mdelay(IDE_WAKEUP_DELAY_MS); #ifdef CONFIG_PMAC_PBOOK pmu_register_sleep_notifier(&idepmac_sleep_notifier); @@ -642,6 +658,7 @@ return result; } +/* Calculate MultiWord DMA timings */ static int pmac_ide_mdma_enable(ide_drive_t *drive, int idx) { @@ -652,18 +669,15 @@ int accessTicks, recTicks; struct hd_driveid *id = drive->id; - /* For now, we don't know these values */ - if (pmac_ide[idx].kind == controller_kl_ata4 && feature != IDE_DMA2_ENABLE) - return 0; - if (pmac_ide[idx].kind != controller_kl_ata4 && feature == IDE_DMA0_ENABLE) - return 0; - /* Set feature on drive */ printk("%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf); if (pmac_ide_do_setfeature(drive, feature)) { printk("%s: Failed !\n", drive->name); return 0; } + + if (!drive->init_speed) + drive->init_speed = feature; /* which drive is it ? */ if (drive->select.all & 0x10) @@ -681,7 +695,10 @@ /* For ata-4 controller, we don't know the calculation */ if (pmac_ide[idx].kind == controller_kl_ata4) { - *timings = 0x00019465; /* MDMA2 */ + accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000); + recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks; + *timings = ((*timings) & 0xffe003ff) | + (accessTicks | (recTicks << 5)) << 10; } else { int halfTick = 0; int origAccessTime = accessTime; @@ -696,7 +713,9 @@ recTicks = 1; cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS; - if ((accessTicks > 1) && + /* KeyLargo ata-3 don't support the half-tick stuff */ + if ((pmac_ide[idx].kind != controller_kl_ata3) && + (accessTicks > 1) && ((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) && ((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) { halfTick = 1; @@ -708,21 +727,21 @@ #ifdef IDE_PMAC_DEBUG printk("ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n", feature & 0xf, *timings); -#endif +#endif + drive->current_speed = feature; return 1; } +/* Calculate Ultra DMA timings */ static int pmac_ide_udma_enable(ide_drive_t *drive, int idx) { byte bits = drive->id->dma_ultra & 0x1f; byte feature = udma_bits_to_command(bits); - u32 timings; + int cycleTime, accessTime; + int rdyToPauseTicks, cycleTicks; + u32 *timings; - /* We support only those values */ - if (feature != IDE_UDMA4_ENABLE && feature != IDE_UDMA2_ENABLE) - return 0; - /* Set feature on drive */ printk("%s: Enabling Ultra DMA %d\n", drive->name, feature & 0xf); if (pmac_ide_do_setfeature(drive, feature)) { @@ -730,23 +749,25 @@ return 0; } - /* Put this channel into UDMA mode. - * This value is set by MacOS on the iBook for U/DMA2 - */ - switch(feature) { - case IDE_UDMA4_ENABLE: - timings = 0x0cd00065; - break; - case IDE_UDMA2_ENABLE: - timings = 0x11100065; - break; - } - + if (!drive->init_speed) + drive->init_speed = feature; + + /* which drive is it ? */ if (drive->select.all & 0x10) - pmac_ide[idx].timings[1] = timings; + timings = &pmac_ide[idx].timings[1]; else - pmac_ide[idx].timings[0] = timings; - + timings = &pmac_ide[idx].timings[0]; + + cycleTime = udma_timings[feature & 0xf].cycleTime; + accessTime = udma_timings[feature & 0xf].accessTime; + + rdyToPauseTicks = SYSCLK_TICKS_UDMA(accessTime * 1000); + cycleTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000); + + *timings = ((*timings) & 0xe00fffff) | + ((cycleTicks << 1) | (rdyToPauseTicks << 5) | 1) << 20; + + drive->current_speed = feature; return 1; } @@ -792,6 +813,12 @@ return 0; } +static int +pmac_ide_tune_chipset(ide_drive_t *drive, byte speed) +{ + return 0; +} + int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); @@ -813,6 +840,7 @@ pmac_ide_dma_onoff(drive, (func == ide_dma_on)); break; case ide_dma_check: + printk("IDE-DMA check !\n"); if (hwif->autodma) pmac_ide_dma_onoff(drive, 1); break; @@ -837,8 +865,21 @@ return (dstat & (RUN|DEAD|ACTIVE)) != RUN; case ide_dma_test_irq: return (in_le32(&dma->status) & (RUN|ACTIVE)) == RUN; + + /* Let's implement tose just in case someone wants them */ + case ide_dma_bad_drive: + case ide_dma_good_drive: + return check_drive_lists(drive, (func == ide_dma_good_drive)); + case ide_dma_verbose: + return report_drive_dmaing(drive); + case ide_dma_retune: + case ide_dma_lostirq: + case ide_dma_timeout: + printk("ide_pmac_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func), func); + return 1; default: - printk(KERN_ERR "pmac_ide_dmaproc: bad func %d\n", func); + printk("ide_pmac_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func); + return 1; } return 0; } @@ -869,8 +910,20 @@ } } feature_set(np, FEATURE_IDE0_reset); - feature_clear(np, FEATURE_IOBUS_enable); feature_clear(np, FEATURE_IDE0_enable); + switch(pmac_ide[i].aapl_bus_id) { + case 0: + feature_set(np, FEATURE_IDE0_reset); + feature_clear(np, FEATURE_IDE0_enable); + break; + case 1: + feature_set(np, FEATURE_IDE1_reset); + feature_clear(np, FEATURE_IDE1_enable); + break; + case 2: + feature_set(np, FEATURE_IDE2_reset); + break; + } pmac_ide[i].timings[0] = 0; pmac_ide[i].timings[1] = 0; } @@ -881,12 +934,30 @@ int j; /* Revive IDE disk and controller */ - feature_set(np, FEATURE_IOBUS_enable); - mdelay(10); - feature_set(np, FEATURE_IDE0_enable); - mdelay(10); - feature_clear(np, FEATURE_IDE0_reset); - mdelay(100); + switch(pmac_ide[i].aapl_bus_id) { + case 0: + feature_set(np, FEATURE_IDE0_reset); + mdelay(10); + feature_set(np, FEATURE_IDE0_enable); + mdelay(10); + feature_clear(np, FEATURE_IDE0_reset); + break; + case 1: + feature_set(np, FEATURE_IDE1_reset); + mdelay(10); + feature_set(np, FEATURE_IDE1_enable); + mdelay(10); + feature_clear(np, FEATURE_IDE1_reset); + break; + case 2: + /* This one exists only for KL, I don't know + about any enable bit */ + feature_set(np, FEATURE_IDE2_reset); + mdelay(10); + feature_clear(np, FEATURE_IDE2_reset); + break; + } + mdelay(IDE_WAKEUP_DELAY_MS); /* Reset timings */ pmac_ide_selectproc(&ide_hwifs[i].drives[0]); @@ -940,7 +1011,7 @@ /* Disable irq during sleep */ disable_irq(pmac_ide[i].irq); ret = check_media_bay_by_base(base, MB_CD); - if (ret == -ENODEV) + if ((ret == -ENODEV) && ide_hwifs[i].drives[0].present) /* not media bay - put the disk to sleep */ idepmac_sleep_disk(i, base); } @@ -953,7 +1024,7 @@ hwif = &ide_hwifs[i]; /* We don't handle media bay devices this way */ ret = check_media_bay_by_base(base, MB_CD); - if (ret == -ENODEV) + if ((ret == -ENODEV) && ide_hwifs[i].drives[0].present) idepmac_wake_disk(i, base); else if (ret == 0) idepmac_wake_bay(i, base); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/ide-probe.c linux/drivers/ide/ide-probe.c --- v2.3.99-pre8/linux/drivers/ide/ide-probe.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/ide/ide-probe.c Mon May 15 11:03:48 2000 @@ -56,6 +56,11 @@ ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */ ide__sti(); /* local CPU only */ ide_fix_driveid(id); + + if (id->word156 == 0x4d42) { + printk("%s: drive->id->word156 == 0x%04x \n", drive->name, drive->id->word156); + } + if (!drive->forced_lun) drive->last_lun = id->last_lun & 0x7; #if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA) @@ -764,9 +769,10 @@ char name[64]; ide_add_generic_settings(hwif->drives + unit); + hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit); sprintf (name, "host%d/bus%d/target%d/lun%d", (hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index, - hwif->channel, unit, 0); + hwif->channel, unit, hwif->drives[unit].lun); hwif->drives[unit].de = devfs_mk_dir (ide_devfs_handle, name, 0, NULL); } @@ -775,9 +781,9 @@ static int hwif_init (ide_hwif_t *hwif) { - ide_drive_t *drive; - void (*rfn)(request_queue_t *); - + request_queue_t *q; + unsigned int unit; + if (!hwif->present) return 0; if (!hwif->irq) { @@ -795,39 +801,7 @@ #endif /* CONFIG_BLK_DEV_HD */ hwif->present = 0; /* we set it back to 1 if all is ok below */ - switch (hwif->major) { - case IDE0_MAJOR: rfn = &do_ide0_request; break; -#if MAX_HWIFS > 1 - case IDE1_MAJOR: rfn = &do_ide1_request; break; -#endif -#if MAX_HWIFS > 2 - case IDE2_MAJOR: rfn = &do_ide2_request; break; -#endif -#if MAX_HWIFS > 3 - case IDE3_MAJOR: rfn = &do_ide3_request; break; -#endif -#if MAX_HWIFS > 4 - case IDE4_MAJOR: rfn = &do_ide4_request; break; -#endif -#if MAX_HWIFS > 5 - case IDE5_MAJOR: rfn = &do_ide5_request; break; -#endif -#if MAX_HWIFS > 6 - case IDE6_MAJOR: rfn = &do_ide6_request; break; -#endif -#if MAX_HWIFS > 7 - case IDE7_MAJOR: rfn = &do_ide7_request; break; -#endif -#if MAX_HWIFS > 8 - case IDE8_MAJOR: rfn = &do_ide8_request; break; -#endif -#if MAX_HWIFS > 9 - case IDE9_MAJOR: rfn = &do_ide9_request; break; -#endif - default: - printk("%s: request_fn NOT DEFINED\n", hwif->name); - return (hwif->present = 0); - } + if (devfs_register_blkdev (hwif->major, hwif->name, ide_fops)) { printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major); return (hwif->present = 0); @@ -860,19 +834,11 @@ read_ahead[hwif->major] = 8; /* (4kB) */ hwif->present = 1; /* success */ - /* - * FIXME(eric) - This needs to be tested. I *think* that this - * is correct. Also, I believe that there is no longer any - * reason to have multiple functions (do_ide[0-7]_request) - * functions - the queuedata field could be used to indicate - * the correct hardware group - either this, or we could add - * a new field to request_queue_t to hold this information. - */ - drive = &hwif->drives[0]; - blk_init_queue(&drive->queue, rfn); - - drive = &hwif->drives[1]; - blk_init_queue(&drive->queue, rfn); + for (unit = 0; unit < MAX_DRIVES; ++unit) { + q = &hwif->drives[unit].queue; + q->queuedata = hwif->hwgroup; + blk_init_queue(q, do_ide_request); + } #if (DEBUG_SPINLOCK > 0) { diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/ide.c linux/drivers/ide/ide.c --- v2.3.99-pre8/linux/drivers/ide/ide.c Thu May 11 15:30:07 2000 +++ linux/drivers/ide/ide.c Mon May 15 11:03:48 2000 @@ -321,6 +321,7 @@ || !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */ || !strncmp(id->model, "SunDisk SDCFB", 13) /* SunDisk */ || !strncmp(id->model, "HAGIWARA HPC", 12) /* Hagiwara */ + || !strncmp(id->model, "LEXAR ATA_FLASH", 15) /* Lexar */ || !strncmp(id->model, "ATA_FLASH", 9)) /* Simple Tech */ { return 1; /* yes, it is a flash memory card */ @@ -767,6 +768,18 @@ args[1] = err; args[2] = IN_BYTE(IDE_NSECTOR_REG); } + } else if (rq->cmd == IDE_DRIVE_TASK) { + byte *args = (byte *) rq->buffer; + rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); + if (args) { + args[0] = stat; + args[1] = err; + args[2] = IN_BYTE(IDE_NSECTOR_REG); + args[3] = IN_BYTE(IDE_SECTOR_REG); + args[4] = IN_BYTE(IDE_LCYL_REG); + args[5] = IN_BYTE(IDE_HCYL_REG); + args[6] = IN_BYTE(IDE_SELECT_REG); + } } spin_lock_irqsave(&io_request_lock, flags); blkdev_dequeue_request(rq); @@ -876,7 +889,7 @@ if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) return ide_stopped; /* retry only "normal" I/O: */ - if (rq->cmd == IDE_DRIVE_CMD) { + if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) { rq->errors = 1; ide_end_drive_cmd(drive, stat, err); return ide_stopped; @@ -1036,7 +1049,20 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq) { byte *args = rq->buffer; - if (args) { + if (args && rq->cmd == IDE_DRIVE_TASK) { + +#ifdef DEBUG + printk("%s: DRIVE_TASK_CMD data=x%02x cmd=0x%02x fr=0x%02x ns=0x%02x sc=0x%02x lcyl=0x%02x hcyl=0x%02x sel=0x%02x\n", + drive->name, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); +#endif + OUT_BYTE(args[1], IDE_FEATURE_REG); + OUT_BYTE(args[3], IDE_SECTOR_REG); + OUT_BYTE(args[4], IDE_LCYL_REG); + OUT_BYTE(args[5], IDE_HCYL_REG); + OUT_BYTE(args[6], IDE_SELECT_REG); + ide_cmd(drive, args[0], args[2], &drive_cmd_intr); + return ide_started; + } else if (args) { #ifdef DEBUG printk("%s: DRIVE_CMD cmd=0x%02x sc=0x%02x fr=0x%02x xx=0x%02x\n", drive->name, args[0], args[1], args[2], args[3]); @@ -1116,7 +1142,7 @@ return startstop; } if (!drive->special.all) { - if (rq->cmd == IDE_DRIVE_CMD) { + if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) { return execute_drive_cmd(drive, rq); } if (drive->driver != NULL) { @@ -1225,7 +1251,7 @@ * the driver. This makes the driver much more friendlier to shared IRQs * than previous designs, while remaining 100% (?) SMP safe and capable. */ -static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) +static void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq) { ide_drive_t *drive; ide_hwif_t *hwif; @@ -1313,73 +1339,13 @@ return &hwif->drives[DEVICE_NR(dev) & 1].queue; } -void do_ide0_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[0].hwgroup, 0); -} - -#if MAX_HWIFS > 1 -void do_ide1_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[1].hwgroup, 0); -} -#endif /* MAX_HWIFS > 1 */ - -#if MAX_HWIFS > 2 -void do_ide2_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[2].hwgroup, 0); -} -#endif /* MAX_HWIFS > 2 */ - -#if MAX_HWIFS > 3 -void do_ide3_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[3].hwgroup, 0); -} -#endif /* MAX_HWIFS > 3 */ - -#if MAX_HWIFS > 4 -void do_ide4_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[4].hwgroup, 0); -} -#endif /* MAX_HWIFS > 4 */ - -#if MAX_HWIFS > 5 -void do_ide5_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[5].hwgroup, 0); -} -#endif /* MAX_HWIFS > 5 */ - -#if MAX_HWIFS > 6 -void do_ide6_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[6].hwgroup, 0); -} -#endif /* MAX_HWIFS > 6 */ - -#if MAX_HWIFS > 7 -void do_ide7_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[7].hwgroup, 0); -} -#endif /* MAX_HWIFS > 7 */ - -#if MAX_HWIFS > 8 -void do_ide8_request (request_queue_t *q) -{ - ide_do_request (ide_hwifs[8].hwgroup, 0); -} -#endif /* MAX_HWIFS > 8 */ - -#if MAX_HWIFS > 9 -void do_ide9_request (request_queue_t *q) +/* + * Passes the stuff to ide_do_request + */ +void do_ide_request(request_queue_t *q) { - ide_do_request (ide_hwifs[9].hwgroup, 0); + ide_do_request(q->queuedata, 0); } -#endif /* MAX_HWIFS > 9 */ /* * ide_timer_expiry() is our timeout function for all drive operations. @@ -1656,16 +1622,8 @@ */ void ide_init_drive_cmd (struct request *rq) { - rq->buffer = NULL; + memset(rq, 0, sizeof(*rq)); rq->cmd = IDE_DRIVE_CMD; - rq->sector = 0; - rq->nr_sectors = 0; - rq->nr_segments = 0; - rq->current_nr_sectors = 0; - rq->sem = NULL; - rq->bh = NULL; - rq->bhtail = NULL; - rq->q = NULL; } /* @@ -2049,8 +2007,10 @@ hwgroup->hwif = HWIF(hwgroup->drive); #ifdef CONFIG_BLK_DEV_IDEDMA - if (hwif->dma_base) + if (hwif->dma_base) { (void) ide_release_dma(hwif); + hwif->dma_base = 0; + } #endif /* CONFIG_BLK_DEV_IDEDMA */ /* @@ -2083,6 +2043,7 @@ init_hwif_data (index); /* restore hwif data to pristine status */ hwif->hwgroup = old_hwif.hwgroup; hwif->tuneproc = old_hwif.tuneproc; + hwif->speedproc = old_hwif.speedproc; hwif->selectproc = old_hwif.selectproc; hwif->resetproc = old_hwif.resetproc; hwif->dmaproc = old_hwif.dmaproc; @@ -2103,7 +2064,7 @@ hwif->pci_devid = old_hwif.pci_devid; #endif /* CONFIG_BLK_DEV_IDEPCI */ hwif->straight8 = old_hwif.straight8; - + hwif->hwif_data = old_hwif.hwif_data; abort: restore_flags(flags); /* all CPUs */ } @@ -2304,24 +2265,24 @@ return val; } -int ide_spin_wait_hwgroup (ide_drive_t *drive, unsigned long *flags) +int ide_spin_wait_hwgroup (ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); unsigned long timeout = jiffies + (3 * HZ); - spin_lock_irqsave(&io_request_lock, *flags); + spin_lock_irq(&io_request_lock); while (hwgroup->busy) { - unsigned long lflags; - spin_unlock_irqrestore(&io_request_lock, *flags); - __save_flags(lflags); /* local CPU only */ + unsigned long flags; + spin_unlock_irq(&io_request_lock); + __save_flags(flags); /* local CPU only */ __sti(); /* local CPU only; needed for jiffies */ if (0 < (signed long)(jiffies - timeout)) { - __restore_flags(lflags); /* local CPU only */ + __restore_flags(flags); printk("%s: channel busy\n", drive->name); return -EBUSY; } - __restore_flags(lflags); /* local CPU only */ - spin_lock_irqsave(&io_request_lock, *flags); + __restore_flags(flags); /* local CPU only */ + spin_lock_irq(&io_request_lock); } return 0; } @@ -2333,7 +2294,6 @@ */ int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val) { - unsigned long flags; int i; u32 *p; @@ -2345,7 +2305,7 @@ return -EINVAL; if (setting->set) return setting->set(drive, val); - if (ide_spin_wait_hwgroup(drive, &flags)) + if (ide_spin_wait_hwgroup(drive)) return -EBUSY; switch (setting->data_type) { case TYPE_BYTE: @@ -2363,7 +2323,7 @@ *p = val; break; } - spin_unlock_irqrestore(&io_request_lock, flags); + spin_unlock_irq(&io_request_lock); return 0; } @@ -2416,6 +2376,9 @@ ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL); ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma); ide_add_setting(drive, "ide_scsi", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->scsi, NULL); + ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 69, 1, 1, &drive->init_speed, NULL); + ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 69, 1, 1, &drive->current_speed, NULL); + ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL); } int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf) @@ -2435,6 +2398,16 @@ return ide_do_drive_cmd(drive, &rq, ide_wait); } +int ide_wait_cmd_task (ide_drive_t *drive, byte *buf) +{ + struct request rq; + + ide_init_drive_cmd(&rq); + rq.cmd = IDE_DRIVE_TASK; + rq.buffer = buf; + return ide_do_drive_cmd(drive, &rq, ide_wait); +} + /* * Delay for *at least* 50ms. As we don't know how much time is left * until the next tick occurs, we wait an extra tick to be safe. @@ -2551,6 +2524,7 @@ case HDIO_DRIVE_CMD: { byte args[4], *argbuf = args; + byte xfer_rate = 0; int argsize = 4; if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (NULL == (void *) arg) @@ -2564,18 +2538,22 @@ return -ENOMEM; memcpy(argbuf, args, 4); } - if (ide_ata66_check(drive, args[0], args[1], args[2])) - goto abort; + + if (set_transfer(drive, args[0], args[1], args[2])) { + xfer_rate = args[1]; + if (ide_ata66_check(drive, args[0], args[1], args[2])) + goto abort; + } err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf); - if (!err && set_transfer(drive, args[0], args[1], args[2])) { -#if 0 + if (!err && xfer_rate) { /* active-retuning-calls future */ - if (HWIF(drive)->tune2proc) - HWIF(drive)->tune2proc(drive, args[1]); -#endif + if ((HWIF(drive)->speedproc) != NULL) + HWIF(drive)->speedproc(drive, xfer_rate); ide_driveid_update(drive); + } else { + printk("%s: \n", drive->name); } abort: if (copy_to_user((void *)arg, argbuf, argsize)) @@ -2584,6 +2562,18 @@ kfree(argbuf); return err; } + case HDIO_DRIVE_TASK: + { + byte args[7], *argbuf = args; + int argsize = 7; + if (!capable(CAP_SYS_ADMIN)) return -EACCES; + if (copy_from_user(args, (void *)arg, 7)) + return -EFAULT; + err = ide_wait_cmd_task(drive, argbuf); + if (copy_to_user((void *)arg, argbuf, argsize)) + err = -EFAULT; + return err; + } case HDIO_SCAN_HWIF: { @@ -3512,37 +3502,9 @@ EXPORT_SYMBOL(ide_intr); EXPORT_SYMBOL(ide_fops); EXPORT_SYMBOL(ide_get_queue); -EXPORT_SYMBOL(do_ide0_request); EXPORT_SYMBOL(ide_add_generic_settings); EXPORT_SYMBOL(ide_devfs_handle); -#if MAX_HWIFS > 1 -EXPORT_SYMBOL(do_ide1_request); -#endif /* MAX_HWIFS > 1 */ -#if MAX_HWIFS > 2 -EXPORT_SYMBOL(do_ide2_request); -#endif /* MAX_HWIFS > 2 */ -#if MAX_HWIFS > 3 -EXPORT_SYMBOL(do_ide3_request); -#endif /* MAX_HWIFS > 3 */ -#if MAX_HWIFS > 4 -EXPORT_SYMBOL(do_ide4_request); -#endif /* MAX_HWIFS > 4 */ -#if MAX_HWIFS > 5 -EXPORT_SYMBOL(do_ide5_request); -#endif /* MAX_HWIFS > 5 */ -#if MAX_HWIFS > 6 -EXPORT_SYMBOL(do_ide6_request); -#endif /* MAX_HWIFS > 6 */ -#if MAX_HWIFS > 7 -EXPORT_SYMBOL(do_ide7_request); -#endif /* MAX_HWIFS > 7 */ -#if MAX_HWIFS > 8 -EXPORT_SYMBOL(do_ide8_request); -#endif /* MAX_HWIFS > 8 */ -#if MAX_HWIFS > 9 -EXPORT_SYMBOL(do_ide9_request); -#endif /* MAX_HWIFS > 9 */ - +EXPORT_SYMBOL(do_ide_request); /* * Driver module */ @@ -3567,6 +3529,7 @@ EXPORT_SYMBOL(ide_revalidate_disk); EXPORT_SYMBOL(ide_cmd); EXPORT_SYMBOL(ide_wait_cmd); +EXPORT_SYMBOL(ide_wait_cmd_task); EXPORT_SYMBOL(ide_delay_50ms); EXPORT_SYMBOL(ide_stall_queue); #ifdef CONFIG_PROC_FS @@ -3652,8 +3615,13 @@ { int index; - for (index = 0; index < MAX_HWIFS; ++index) + for (index = 0; index < MAX_HWIFS; ++index) { ide_unregister(index); +#ifdef CONFIG_BLK_DEV_IDEDMA + if (ide_hwifs[index].dma_base) + (void) ide_release_dma(&ide_hwifs[index]); +#endif /* CONFIG_BLK_DEV_IDEDMA */ + } #ifdef CONFIG_PROC_FS proc_ide_destroy(); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/pdc202xx.c linux/drivers/ide/pdc202xx.c --- v2.3.99-pre8/linux/drivers/ide/pdc202xx.c Mon Mar 27 08:08:24 2000 +++ linux/drivers/ide/pdc202xx.c Mon May 15 11:03:48 2000 @@ -262,59 +262,99 @@ #endif /* PDC202XX_DECODE_REGISTER_INFO */ -/* 0 1 2 3 4 5 6 7 8 - * 960, 480, 390, 300, 240, 180, 120, 90, 60 - * 180, 150, 120, 90, 60 - * DMA_Speed - * 180, 120, 90, 90, 90, 60, 30 - * 11, 5, 4, 3, 2, 1, 0 - */ -static int config_chipset_for_pio (ide_drive_t *drive, byte pio) +static int pdc202xx_tune_chipset (ide_drive_t *drive, byte speed) { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - byte drive_pci, speed; - byte AP, BP, TA, TB; - int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - int err; + unsigned int drive_conf; + int err; + byte drive_pci, AP, BP, CP, DP; + byte TA = 0, TB = 0, TC = 0; - switch (drive_number) { + switch (drive->dn) { case 0: drive_pci = 0x60; break; case 1: drive_pci = 0x64; break; case 2: drive_pci = 0x68; break; case 3: drive_pci = 0x6c; break; - default: return 1; + default: return -1; } + if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) return -1; + + pci_read_config_dword(dev, drive_pci, &drive_conf); pci_read_config_byte(dev, (drive_pci), &AP); pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + pci_read_config_byte(dev, (drive_pci)|0x03, &DP); + +#ifdef CONFIG_BLK_DEV_IDEDMA + if (speed >= XFER_SW_DMA_0) { + if ((BP & 0xF0) && (CP & 0x0F)) { + /* clear DMA modes of upper 842 bits of B Register */ + /* clear PIO forced mode upper 1 bit of B Register */ + pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0xF0); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + + /* clear DMA modes of lower 8421 bits of C Register */ + pci_write_config_byte(dev, (drive_pci)|0x02, CP & ~0x0F); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + } + } else { +#else + { +#endif /* CONFIG_BLK_DEV_IDEDMA */ + if ((AP & 0x0F) || (BP & 0x07)) { + /* clear PIO modes of lower 8421 bits of A Register */ + pci_write_config_byte(dev, (drive_pci), AP & ~0x0F); + pci_read_config_byte(dev, (drive_pci), &AP); + + /* clear PIO modes of lower 421 bits of B Register */ + pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0x07); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + } + } - if ((AP & 0x0F) || (BP & 0x07)) { - /* clear PIO modes of lower 8421 bits of A Register */ - pci_write_config_byte(dev, (drive_pci), AP & ~0x0F); - pci_read_config_byte(dev, (drive_pci), &AP); - - /* clear PIO modes of lower 421 bits of B Register */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0x07); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + switch(speed) { +#ifdef CONFIG_BLK_DEV_IDEDMA + case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; /* speed 8 == UDMA mode 4 */ + case XFER_UDMA_3: TB = 0x40; TC = 0x02; break; /* speed 7 == UDMA mode 3 */ + case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; /* speed 6 == UDMA mode 2 */ + case XFER_UDMA_1: TB = 0x40; TC = 0x02; break; /* speed 5 == UDMA mode 1 */ + case XFER_UDMA_0: TB = 0x60; TC = 0x03; break; /* speed 4 == UDMA mode 0 */ + case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break; /* speed 4 == MDMA mode 2 */ + case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break; /* speed 3 == MDMA mode 1 */ + case XFER_MW_DMA_0: TB = 0x60; TC = 0x05; break; /* speed 2 == MDMA mode 0 */ + case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break; /* speed 0 == SDMA mode 2 */ + case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break; /* speed 1 == SDMA mode 1 */ + case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break; /* speed 0 == SDMA mode 0 */ +#endif /* CONFIG_BLK_DEV_IDEDMA */ + case XFER_PIO_4: TA = 0x01; TB = 0x04; break; + case XFER_PIO_3: TA = 0x02; TB = 0x06; break; + case XFER_PIO_2: TA = 0x03; TB = 0x08; break; + case XFER_PIO_1: TA = 0x05; TB = 0x0C; break; + case XFER_PIO_0: + default: TA = 0x09; TB = 0x13; break; } - pio = (pio == 5) ? 4 : pio; - switch (ide_get_best_pio_mode(drive, 255, pio, NULL)) { - case 4:speed = XFER_PIO_4; TA=0x01; TB=0x04; break; - case 3:speed = XFER_PIO_3; TA=0x02; TB=0x06; break; - case 2:speed = XFER_PIO_2; TA=0x03; TB=0x08; break; - case 1:speed = XFER_PIO_1; TA=0x05; TB=0x0C; break; - case 0: - default:speed = XFER_PIO_0; TA=0x09; TB=0x13; break; +#ifdef CONFIG_BLK_DEV_IDEDMA + if (speed >= XFER_SW_DMA_0) { + pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); + pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); + } else { +#else + { +#endif /* CONFIG_BLK_DEV_IDEDMA */ + pci_write_config_byte(dev, (drive_pci), AP|TA); + pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); } - pci_write_config_byte(dev, (drive_pci), AP|TA); - pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); #if PDC202XX_DECODE_REGISTER_INFO pci_read_config_byte(dev, (drive_pci), &AP); @@ -333,13 +373,30 @@ #if PDC202XX_DEBUG_DRIVE_INFO printk("%s: %s drive%d 0x%08x ", drive->name, ide_xfer_verbose(speed), - drive_number, drive_conf); + drive->dn, drive_conf); pci_read_config_dword(dev, drive_pci, &drive_conf); printk("0x%08x\n", drive_conf); #endif /* PDC202XX_DEBUG_DRIVE_INFO */ return err; } +/* 0 1 2 3 4 5 6 7 8 + * 960, 480, 390, 300, 240, 180, 120, 90, 60 + * 180, 150, 120, 90, 60 + * DMA_Speed + * 180, 120, 90, 90, 90, 60, 30 + * 11, 5, 4, 3, 2, 1, 0 + */ +static int config_chipset_for_pio (ide_drive_t *drive, byte pio) +{ + byte speed = 0x00; + + pio = (pio == 5) ? 4 : pio; + speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL); + + return ((int) pdc202xx_tune_chipset(drive, speed)); +} + static void pdc202xx_tune_drive (ide_drive_t *drive, byte pio) { (void) config_chipset_for_pio(drive, pio); @@ -352,15 +409,15 @@ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; unsigned long high_16 = dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK; + unsigned long dma_base = hwif->dma_base; + byte unit = (drive->select.b.unit & 0x01); - int err; unsigned int drive_conf; byte drive_pci; byte test1, test2, speed = -1; - byte AP, BP, CP, DP, TB, TC; + byte AP; unsigned short EP; byte CLKSPD = IN_BYTE(high_16 + 0x11); - int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0; byte udma_33 = ultra ? (inb(high_16 + 0x001f) & 1) : 0; @@ -397,9 +454,9 @@ * check to make sure drive on same channel * is u66 capable */ - if (hwif->drives[!(drive_number%2)].id) { - if ((hwif->drives[!(drive_number%2)].id->dma_ultra & 0x0010) || - (hwif->drives[!(drive_number%2)].id->dma_ultra & 0x0008)) { + if (hwif->drives[!(drive->dn%2)].id) { + if ((hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0010) || + (hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0008)) { OUT_BYTE(CLKSPD | mask, (high_16 + 0x11)); } else { OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11)); @@ -410,7 +467,7 @@ } } - switch(drive_number) { + switch(drive->dn) { case 0: drive_pci = 0x60; pci_read_config_dword(dev, drive_pci, &drive_conf); if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4)) @@ -451,101 +508,34 @@ chipset_is_set: - if (drive->media != ide_disk) - return ide_dma_off_quietly; + if (drive->media != ide_disk) return ide_dma_off_quietly; pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - pci_read_config_byte(dev, (drive_pci)|0x03, &DP); - - if (id->capability & 4) { /* IORDY_EN */ + if (id->capability & 4) /* IORDY_EN */ pci_write_config_byte(dev, (drive_pci), AP|IORDY_EN); - pci_read_config_byte(dev, (drive_pci), &AP); - } - - if (drive->media == ide_disk) { /* PREFETCH_EN */ - pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN); - pci_read_config_byte(dev, (drive_pci), &AP); - } - - if ((BP & 0xF0) && (CP & 0x0F)) { - /* clear DMA modes of upper 842 bits of B Register */ - /* clear PIO forced mode upper 1 bit of B Register */ - pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0xF0); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - - /* clear DMA modes of lower 8421 bits of C Register */ - pci_write_config_byte(dev, (drive_pci)|0x02, CP & ~0x0F); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - } - pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + if (drive->media == ide_disk) /* PREFETCH_EN */ + pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN); - if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) { - /* speed 8 == UDMA mode 4 == speed 6 plus cable */ - speed = XFER_UDMA_4; TB = 0x20; TC = 0x01; - } else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) { - /* speed 7 == UDMA mode 3 == speed 5 plus cable */ - speed = XFER_UDMA_3; TB = 0x40; TC = 0x02; - } else if ((id->dma_ultra & 0x0004) && (udma_33)) { - /* speed 6 == UDMA mode 2 */ - speed = XFER_UDMA_2; TB = 0x20; TC = 0x01; - } else if ((id->dma_ultra & 0x0002) && (udma_33)) { - /* speed 5 == UDMA mode 1 */ - speed = XFER_UDMA_1; TB = 0x40; TC = 0x02; - } else if ((id->dma_ultra & 0x0001) && (udma_33)) { - /* speed 4 == UDMA mode 0 */ - speed = XFER_UDMA_0; TB = 0x60; TC = 0x03; - } else if (id->dma_mword & 0x0004) { - /* speed 4 == DMA mode 2 multi-word */ - speed = XFER_MW_DMA_2; TB = 0x60; TC = 0x03; - } else if (id->dma_mword & 0x0002) { - /* speed 3 == DMA mode 1 multi-word */ - speed = XFER_MW_DMA_1; TB = 0x60; TC = 0x04; - } else if (id->dma_mword & 0x0001) { - /* speed 2 == DMA mode 0 multi-word */ - speed = XFER_MW_DMA_0; TB = 0x60; TC = 0x05; - } else if (id->dma_1word & 0x0004) { - /* speed 2 == DMA mode 2 single-word */ - speed = XFER_SW_DMA_2; TB = 0x60; TC = 0x05; - } else if (id->dma_1word & 0x0002) { - /* speed 1 == DMA mode 1 single-word */ - speed = XFER_SW_DMA_1; TB = 0x80; TC = 0x06; - } else if (id->dma_1word & 0x0001) { - /* speed 0 == DMA mode 0 single-word */ - speed = XFER_SW_DMA_0; TB = 0xC0; TC = 0x0B; - } else { + if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) speed = XFER_UDMA_4; + else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) speed = XFER_UDMA_3; + else if ((id->dma_ultra & 0x0004) && (udma_33)) speed = XFER_UDMA_2; + else if ((id->dma_ultra & 0x0002) && (udma_33)) speed = XFER_UDMA_1; + else if ((id->dma_ultra & 0x0001) && (udma_33)) speed = XFER_UDMA_0; + else if (id->dma_mword & 0x0004) speed = XFER_MW_DMA_2; + else if (id->dma_mword & 0x0002) speed = XFER_MW_DMA_1; + else if (id->dma_mword & 0x0001) speed = XFER_MW_DMA_0; + else if (id->dma_1word & 0x0004) speed = XFER_SW_DMA_2; + else if (id->dma_1word & 0x0002) speed = XFER_SW_DMA_1; + else if (id->dma_1word & 0x0001) speed = XFER_SW_DMA_0; + else { /* restore original pci-config space */ pci_write_config_dword(dev, drive_pci, drive_conf); return ide_dma_off_quietly; } - pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); - pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); - -#if PDC202XX_DECODE_REGISTER_INFO - pci_read_config_byte(dev, (drive_pci), &AP); - pci_read_config_byte(dev, (drive_pci)|0x01, &BP); - pci_read_config_byte(dev, (drive_pci)|0x02, &CP); - - decode_registers(REG_A, AP); - decode_registers(REG_B, BP); - decode_registers(REG_C, CP); - decode_registers(REG_D, DP); -#endif /* PDC202XX_DECODE_REGISTER_INFO */ - - err = ide_config_drive_speed(drive, speed); - -#if PDC202XX_DEBUG_DRIVE_INFO - printk("%s: %s drive%d 0x%08x ", - drive->name, ide_xfer_verbose(speed), - drive_number, drive_conf); - pci_read_config_dword(dev, drive_pci, &drive_conf); - printk("0x%08x\n", drive_conf); -#endif /* PDC202XX_DEBUG_DRIVE_INFO */ + outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2); + (void) pdc202xx_tune_chipset(drive, speed); return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : @@ -716,6 +706,7 @@ void __init ide_init_pdc202xx (ide_hwif_t *hwif) { hwif->tuneproc = &pdc202xx_tune_drive; + hwif->speedproc = &pdc202xx_tune_chipset; #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/piix.c linux/drivers/ide/piix.c --- v2.3.99-pre8/linux/drivers/ide/piix.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/ide/piix.c Mon May 15 11:03:48 2000 @@ -112,6 +112,7 @@ p += sprintf(p, "\n Intel PIIX4 Ultra 66 Chipset.\n"); break; case PCI_DEVICE_ID_INTEL_82801AB_1: + case PCI_DEVICE_ID_INTEL_82443MX_1: case PCI_DEVICE_ID_INTEL_82371AB: p += sprintf(p, "\n Intel PIIX4 Ultra 33 Chipset.\n"); break; @@ -258,28 +259,18 @@ } #if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING) -static int piix_config_drive_for_dma (ide_drive_t *drive) +static int piix_tune_chipset (ide_drive_t *drive, byte speed) { - struct hd_driveid *id = drive->id; ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - - int sitre; - short reg4042, reg44, reg48, reg4a, reg54; - byte speed; - byte maslave = hwif->channel ? 0x42 : 0x40; - byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0; - int ultra66 = ((dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) || - (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0; - int ultra = ((ultra66) || - (dev->device == PCI_DEVICE_ID_INTEL_82371AB) || - (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1)) ? 1 : 0; - int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); - int a_speed = 2 << (drive_number * 4); - int u_flag = 1 << drive_number; - int v_flag = 0x10 << drive_number; + int a_speed = 2 << (drive->dn * 4); + int u_flag = 1 << drive->dn; + int v_flag = 0x10 << drive->dn; int u_speed = 0; + int err = 0; + int sitre; + short reg4042, reg44, reg48, reg4a, reg54; pci_read_config_word(dev, maslave, ®4042); sitre = (reg4042 & 0x4000) ? 1 : 0; @@ -288,29 +279,16 @@ pci_read_config_word(dev, 0x4a, ®4a); pci_read_config_word(dev, 0x54, ®54); - if ((id->dma_ultra & 0x0010) && (ultra)) { - u_speed = 2 << (drive_number * 4); - speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0008) && (ultra)) { - u_speed = 1 << (drive_number * 4); - speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0004) && (ultra)) { - u_speed = 2 << (drive_number * 4); - speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra)) { - u_speed = 1 << (drive_number * 4); - speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra)) { - u_speed = 0 << (drive_number * 4); - speed = XFER_UDMA_0; - } else if (id->dma_mword & 0x0004) { - speed = XFER_MW_DMA_2; - } else if (id->dma_mword & 0x0002) { - speed = XFER_MW_DMA_1; - } else if (id->dma_1word & 0x0004) { - speed = XFER_SW_DMA_2; - } else { - speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); + switch(speed) { + case XFER_UDMA_4: + case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break; + case XFER_UDMA_3: + case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break; + case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break; + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_SW_DMA_2: break; + default: return -1; } if (speed >= XFER_UDMA_0) { @@ -328,7 +306,6 @@ pci_write_config_word(dev, 0x54, reg54 & ~v_flag); } } - if (speed < XFER_UDMA_0) { if (reg48 & u_flag) pci_write_config_word(dev, 0x48, reg48 & ~u_flag); @@ -340,11 +317,52 @@ piix_tune_drive(drive, piix_dma_2_pio(speed)); - (void) ide_config_drive_speed(drive, speed); - #if PIIX_DEBUG_DRIVE_INFO - printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive_number); + printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn); #endif /* PIIX_DEBUG_DRIVE_INFO */ + if (!drive->init_speed) + drive->init_speed = speed; + err = ide_config_drive_speed(drive, speed); + drive->current_speed = speed; + return err; +} + +static int piix_config_drive_for_dma (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + struct pci_dev *dev = hwif->pci_dev; + byte speed; + + byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0; + int ultra66 = ((dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) || + (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0; + int ultra = ((ultra66) || + (dev->device == PCI_DEVICE_ID_INTEL_82371AB) || + (dev->device == PCI_DEVICE_ID_INTEL_82443MX_1) || + (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1)) ? 1 : 0; + + if ((id->dma_ultra & 0x0010) && (ultra)) { + speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2; + } else if ((id->dma_ultra & 0x0008) && (ultra)) { + speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1; + } else if ((id->dma_ultra & 0x0004) && (ultra)) { + speed = XFER_UDMA_2; + } else if ((id->dma_ultra & 0x0002) && (ultra)) { + speed = XFER_UDMA_1; + } else if ((id->dma_ultra & 0x0001) && (ultra)) { + speed = XFER_UDMA_0; + } else if (id->dma_mword & 0x0004) { + speed = XFER_MW_DMA_2; + } else if (id->dma_mword & 0x0002) { + speed = XFER_MW_DMA_1; + } else if (id->dma_1word & 0x0004) { + speed = XFER_SW_DMA_2; + } else { + speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL); + } + + (void) piix_tune_chipset(drive, speed); return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : ((id->dma_ultra >> 8) & 7) ? ide_dma_on : @@ -413,6 +431,7 @@ #ifdef CONFIG_PIIX_TUNING hwif->autodma = 1; hwif->dmaproc = &piix_dmaproc; + hwif->speedproc = &piix_tune_chipset; #endif /* CONFIG_PIIX_TUNING */ #endif /* !CONFIG_BLK_DEV_IDEDMA */ } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/qd6580.c linux/drivers/ide/qd6580.c --- v2.3.99-pre8/linux/drivers/ide/qd6580.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/ide/qd6580.c Mon May 15 11:03:48 2000 @@ -1,12 +1,21 @@ /* - * linux/drivers/ide/qd6580.c Version 0.02 Feb 09, 1996 + * linux/drivers/ide/qd6580.c Version 0.03 May 13, 2000 * - * Copyright (C) 1996 Linus Torvalds & author (see below) + * Copyright (C) 1996-2000 Linus Torvalds & author (see below) */ /* - * QDI QD6580 EIDE controller fast support by Colten Edwards. - * No net access, but (maybe) can be reached at pje120@cs.usask.ca + * Version 0.03 Cleaned auto-tune, added probe + * + * QDI QD6580 EIDE controller fast support + * + * To activate controller support use kernel parameter "ide0=qd6580" + * To enable tuning use kernel parameter "ide0=autotune" + */ + +/* + * Rewritten from the work of Colten Edwards by + * Samuel Thibault */ #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -27,42 +36,237 @@ #include "ide_modes.h" /* - * Register 0xb3 looks like: - * 0x4f is fast mode3 ? - * 0x3f is medium mode2 ? - * 0x2f is slower mode1 ? - * 0x1f is slower yet mode0 ? - * 0x0f ??? ??? + * I/O ports are 0xb0 0xb1 0xb2 and 0xb3 + * or 0x30 0x31 0x32 and 0x33 + * -- this is a dual IDE interface with I/O chips + * + * More research on qd6580 being done by willmore@cig.mot.com (David) + */ + +/* + * 0xb0: Timer1 * - * Don't know whether this sets BOTH drives, or just the first drive. - * Don't know if there is a separate setting for the second drive. + * + * 0xb1: Status * - * Feel free to patch this if you have one of these beasts - * and can work out the answers! + * && 0xf0 is either 0b1010000 or 0b01010000, or else it isn't a qd6580 + * bit 3 & 2: unknown (useless ?) I have 0 & 1, respectively + * bit 1: 1 if qd6580 baseport is 0xb0 + * 0 if qd6580 baseport is 0x30 + * bit 0: 1 if ide baseport is 0x1f0 + * 0 if ide baseport is 0x170 + * (? Strange: the Dos driver uses it, and then forces baseport to 0x1f0 ?) + * + * + * 0xb2: Timer2 * - * I/O ports are 0xb0 0xb2 and 0xb3 + * + * 0xb3: Control * - * More research on qd6580 being done by willmore@cig.mot.com (David) - * -- this is apparently a *dual* IDE interface + * bits 0-3 are always set 1 + * bit 6 : if 1, must be set 1 + * bit 1 : if 1, bit 7 must be set 1 + * bit 0 : if 1, drives are independant, we can have two different timers for + * the two drives. + * if 0, we have to take the slowest drive into account, + * but we may tune the second hwif ? */ -static void tune_qd6580 (ide_drive_t *drive, byte pio) +typedef struct ide_hd_timings_s { + int active_time; /* Active pulse (ns) minimum */ + int recovery_time; /* Recovery pulse (ns) minimum */ +} ide_hd_timings_t; + +static int basePort; /* base port address (0x30 or 0xb0) */ +static byte status; /* status register of qd6580 */ +static byte control; /* control register of qd6580 */ + +/* truncates a in [b,c] */ +#define IDE_IN(a,b,c) ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) ) + +static int bus_clock; /* Vesa local bus clock (ns) */ +static int tuned=0; /* to remember whether we've already been tuned */ + +/* + * tune_drive + * + * Finds timings for the specified drive, returns it in struc t + */ + +static void tune_drive ( ide_drive_t *drive, byte pio, ide_hd_timings_t *t) +{ + ide_pio_data_t d; + + t->active_time = 0xaf; + t->recovery_time = 0x19f; /* worst cases values from the dos driver */ + + if (drive->present == 0) { /* not present : free to give any timing */ + t->active_time = 0x0; + t->recovery_time = 0x0; + return; + } + + pio = ide_get_best_pio_mode(drive, pio, 4, &d); + + if (pio) { + + switch (pio) { + case 0: break; + case 3: t->active_time = 0x56; + t->recovery_time = d.cycle_time-0x66; + break; + case 4: t->active_time = 0x46; + t->recovery_time = d.cycle_time-0x3d; + break; + default: if (d.cycle_time >= 0xb4) { + t->active_time = 0x6e; + t->recovery_time = d.cycle_time - 0x78; + } else { + t->active_time = ide_pio_timings[pio].active_time; + t->recovery_time = d.cycle_time + -t->active_time + -ide_pio_timings[pio].setup_time; + } + } + } + printk("%s: PIO mode%d, tim1=%dns tim2=%dns\n", drive->name, pio, t->active_time, t->recovery_time); +} + +/* + * tune_ide + * + * Tunes the whole ide, ie tunes each drives, and takes the worst timings + * to tune qd6580 + */ + +static void tune_ide ( ide_hwif_t *hwif, byte pio ) { unsigned long flags; + ide_hd_timings_t t[2]={{0,0},{0,0}}; + + byte active_cycle; + byte recovery_cycle; + byte parameter; + int bus_speed = ide_system_bus_speed (); + + bus_clock = 1000 / bus_speed; + + save_flags(flags); /* all CPUs */ + cli(); /* all CPUs */ + outb( (bus_clock<30) ? 0x0 : 0x0a, basePort + 0x02); + outb( 0x40 | ((control & 0x02) ? 0x9f:0x1f), basePort+0x03); + restore_flags(flags); - pio = ide_get_best_pio_mode(drive, pio, 3, NULL); + tune_drive (&hwif->drives[0], pio, &t[0]); + tune_drive (&hwif->drives[1], pio, &t[1]); - save_flags(flags); /* all CPUs */ - cli(); /* all CPUs */ - outb_p(0x8d,0xb0); - outb_p(0x0 ,0xb2); - outb_p(((pio+1)<<4)|0x0f,0xb3); + t[0].active_time = IDE_MAX(t[0].active_time, t[1].active_time); + t[0].recovery_time = IDE_MAX(t[0].recovery_time,t[1].recovery_time); + + active_cycle = 17-IDE_IN(t[0].active_time / bus_clock + 1, 2, 17); + recovery_cycle = 15-IDE_IN(t[0].recovery_time / bus_clock + 1, 2, 15); + + parameter=active_cycle | (recovery_cycle<<4); + + printk("%s: tim1=%dns tim2=%dns => %#x\n", hwif->name, t[0].active_time, t[0].recovery_time, parameter); + + save_flags(flags); /* all CPUs */ + cli(); /* all CPUs */ + outb_p(parameter,0xb0); inb(0x3f6); restore_flags(flags); /* all CPUs */ + +} + +/* + * tune_qd6580 + * + * tunes the hwif if not tuned + */ + +static void tune_qd6580 (ide_drive_t *drive, byte pio) +{ + if (! tuned) { + tune_ide(HWIF(drive), pio); + tuned = 1; + } +} + +/* + * testreg + * + * tests if the given port is a register + */ + +static int __init testreg(int port) +{ + byte savereg; + byte readreg; + unsigned long flags; + + save_flags(flags); /* all CPUs */ + cli(); /* all CPUs */ + savereg = inb(port); + outb_p(0x15,port); /* safe value */ + readreg = inb_p(port); + outb(savereg,port); + restore_flags(flags); /* all CPUs */ + + if (savereg == 0x15) { + printk("Outch ! the probe for qd6580 isn't reliable !\n"); + printk("Please contact samuel.thibault@fnac.net to tell about your hardware\n"); + printk("Assuming qd6580 is present"); + } + + return (readreg == 0x15); } +/* + * trybase: + * + * tries to find a qd6580 at the given base and save it if found + */ + +static int __init trybase (int base) +{ + unsigned long flags; + + save_flags(flags); /* all CPUs */ + cli(); /* all CPUs */ + status = inb(base+0x01); + control = inb(base+0x03); + restore_flags(flags); /* all CPUs */ + + if (((status & 0xf0) != 0x50) && ((status & 0xf0) != 0xa0)) return(0); + if (! ( ((status & 0x02) == 0x0) == (base == 0x30) ) ) return (0); + + /* Seems to be OK, let's use it */ + + basePort = base; + return(testreg(base)); +} + +/* + * probe: + * + * probes qd6580 at 0xb0 (the default) or 0x30 + */ + +static int __init probe (void) +{ + return (trybase(0xb0) ? 1 : trybase(0x30)); +} + + void __init init_qd6580 (void) { + if (! probe()) { + printk("qd6580: not found\n"); + return; + } + + printk("qd6580: base=%#x, status=%#x, control=%#x\n", basePort, status, control); + ide_hwifs[0].chipset = ide_qd6580; ide_hwifs[1].chipset = ide_qd6580; ide_hwifs[0].tuneproc = &tune_qd6580; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/sis5513.c linux/drivers/ide/sis5513.c --- v2.3.99-pre8/linux/drivers/ide/sis5513.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/ide/sis5513.c Mon May 15 11:03:48 2000 @@ -227,9 +227,8 @@ ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); byte reg4bh = 0; - byte rw_prefetch = (0x11 << drive_number); + byte rw_prefetch = (0x11 << drive->dn); pci_read_config_byte(dev, 0x4b, ®4bh); if (drive->media != ide_disk) @@ -248,12 +247,8 @@ unsigned short eide_pio_timing[6] = {600, 390, 240, 180, 120, 90}; unsigned short xfer_pio = drive->id->eide_pio_modes; - int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01)); -#if 0 config_drive_art_rwp(drive); -#endif - pio = ide_get_best_pio_mode(drive, 255, pio, NULL); if (xfer_pio> 4) @@ -281,7 +276,7 @@ * Cycle time 20T (600ns) 13T (390ns) 8T (240ns) 6T (180ns) 4T (120ns) */ - switch(drive_number) { + switch(drive->dn) { case 0: drive_pci = 0x40; break; case 1: drive_pci = 0x42; break; case 2: drive_pci = 0x44; break; @@ -329,7 +324,7 @@ return err; } -#undef SIS5513_TUNEPROC +#define SIS5513_TUNEPROC #ifdef SIS5513_TUNEPROC static void sis5513_tune_drive (ide_drive_t *drive, byte pio) @@ -354,7 +349,6 @@ unsigned long dma_base = hwif->dma_base; byte unit = (drive->select.b.unit & 0x01); byte speed = 0x00, unmask = 0xE0, four_two = 0x00; - int drive_number = ((hwif->channel ? 2 : 0) + unit); byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0; if (host_dev) { @@ -370,7 +364,7 @@ } } - switch(drive_number) { + switch(drive->dn) { case 0: drive_pci = 0x40;break; case 1: drive_pci = 0x42;break; case 2: drive_pci = 0x44;break; @@ -438,7 +432,7 @@ err = ide_config_drive_speed(drive, speed); #if SIS5513_DEBUG_DRIVE_INFO - printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive_number); + printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn); #endif /* SIS5513_DEBUG_DRIVE_INFO */ return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on : diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/via82cxxx.c linux/drivers/ide/via82cxxx.c --- v2.3.99-pre8/linux/drivers/ide/via82cxxx.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/ide/via82cxxx.c Mon May 15 11:03:48 2000 @@ -115,6 +115,7 @@ struct chipset_bus_clock_list_entry via82cxxx_type_one [] = { /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */ +#ifdef CONFIG_BLK_DEV_IDEDMA { XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { XFER_UDMA_3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { XFER_UDMA_2, 0x60, 0x20, 0x60, 0x20, 0x60, 0x21, 0x00, 0x00 }, @@ -124,7 +125,7 @@ { XFER_MW_DMA_2, 0x03, 0x20, 0x03, 0x20, 0x03, 0x21, 0x00, 0x00 }, { XFER_MW_DMA_1, 0x03, 0x31, 0x03, 0x31, 0x03, 0x32, 0x00, 0x00 }, { XFER_MW_DMA_0, 0x03, 0x31, 0x03, 0x31, 0x03, 0x32, 0x00, 0x00 }, - +#endif /* CONFIG_BLK_DEV_IDEDMA */ { XFER_PIO_4, 0x03, 0x20, 0x03, 0x20, 0x03, 0x21, 0x00, 0x00 }, { XFER_PIO_3, 0x03, 0x31, 0x03, 0x31, 0x03, 0x32, 0x00, 0x00 }, { XFER_PIO_2, 0x03, 0x65, 0x03, 0x65, 0x03, 0x76, 0x00, 0x00 }, @@ -135,6 +136,7 @@ struct chipset_bus_clock_list_entry via82cxxx_type_two [] = { /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */ +#ifdef CONFIG_BLK_DEV_IDEDMA { XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { XFER_UDMA_3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { XFER_UDMA_2, 0xE0, 0x20, 0xE0, 0x20, 0xE1, 0x31, 0xE1, 0x32 }, @@ -144,7 +146,7 @@ { XFER_MW_DMA_2, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 }, { XFER_MW_DMA_1, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 }, { XFER_MW_DMA_0, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 }, - +#endif /* CONFIG_BLK_DEV_IDEDMA */ { XFER_PIO_4, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 }, { XFER_PIO_3, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 }, { XFER_PIO_2, 0x03, 0x65, 0x03, 0x65, 0x03, 0x87, 0x03, 0xA8 }, @@ -155,6 +157,7 @@ struct chipset_bus_clock_list_entry via82cxxx_type_three [] = { /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */ +#ifdef CONFIG_BLK_DEV_IDEDMA { XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { XFER_UDMA_3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { XFER_UDMA_2, 0xE0, 0x20, 0xE0, 0x20, 0xE1, 0x31, 0xE1, 0x32 }, @@ -164,7 +167,7 @@ { XFER_MW_DMA_2, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 }, { XFER_MW_DMA_1, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 }, { XFER_MW_DMA_0, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 }, - +#endif /* CONFIG_BLK_DEV_IDEDMA */ { XFER_PIO_4, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 }, { XFER_PIO_3, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 }, { XFER_PIO_2, 0x03, 0x65, 0x03, 0x65, 0x03, 0x87, 0x03, 0xA8 }, @@ -175,6 +178,7 @@ struct chipset_bus_clock_list_entry via82cxxx_type_four [] = { /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */ +#ifdef CONFIG_BLK_DEV_IDEDMA { XFER_UDMA_4, 0x00, 0x00, 0xE0, 0x20, 0xE1, 0x31, 0x00, 0x00 }, { XFER_UDMA_3, 0x00, 0x00, 0xE1, 0x20, 0xE2, 0x31, 0x00, 0x00 }, { XFER_UDMA_2, 0x00, 0x00, 0xE2, 0x20, 0xE4, 0x31, 0x00, 0x00 }, @@ -184,7 +188,7 @@ { XFER_MW_DMA_2, 0x00, 0x00, 0x03, 0x20, 0x03, 0x31, 0x00, 0x00 }, { XFER_MW_DMA_1, 0x00, 0x00, 0x03, 0x31, 0x03, 0x42, 0x00, 0x00 }, { XFER_MW_DMA_0, 0x00, 0x00, 0x03, 0x31, 0x03, 0x42, 0x00, 0x00 }, - +#endif /* CONFIG_BLK_DEV_IDEDMA */ { XFER_PIO_4, 0x00, 0x00, 0x03, 0x20, 0x03, 0x31, 0x00, 0x00 }, { XFER_PIO_3, 0x00, 0x00, 0x03, 0x31, 0x03, 0x42, 0x00, 0x00 }, { XFER_PIO_2, 0x00, 0x00, 0x03, 0x65, 0x03, 0x87, 0x00, 0x00 }, @@ -651,8 +655,7 @@ { ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - byte unit = (drive->select.b.unit & 0x01); - int drive_number = ((hwif->channel ? 2 : 0) + unit); + struct chipset_bus_clock_list_entry * temp_table = NULL; byte ata2_pci = 0x00; byte ata3_pci = 0x00; @@ -662,7 +665,10 @@ int bus_speed = system_bus_clock(); - switch(drive_number) { + if (via82cxxx_table == NULL) + return -1; + + switch(drive->dn) { case 0: ata2_pci = 0x4b; ata3_pci = 0x53; break; case 1: ata2_pci = 0x4a; ata3_pci = 0x52; break; case 2: ata2_pci = 0x49; ata3_pci = 0x51; break; @@ -671,16 +677,26 @@ return -1; } + if ((via82cxxx_table == via82cxxx_type_four) && (speed <= XFER_UDMA_2)) { + temp_table = via82cxxx_type_three; + } else { + temp_table = via82cxxx_table; + } + pci_read_config_byte(dev, ata2_pci, &timing); - timing = pci_bus_clock_list(speed, bus_speed, via82cxxx_table); + timing = pci_bus_clock_list(speed, bus_speed, temp_table); pci_write_config_byte(dev, ata2_pci, timing); pci_read_config_byte(dev, ata3_pci, &ultra); - ultra = pci_bus_clock_list_ultra(speed, bus_speed, via82cxxx_table); + ultra = pci_bus_clock_list_ultra(speed, bus_speed, temp_table); pci_write_config_byte(dev, ata3_pci, ultra); + if (!drive->init_speed) + drive->init_speed = speed; + err = ide_config_drive_speed(drive, speed); + drive->current_speed = speed; return(err); } @@ -845,6 +861,7 @@ struct pci_dev *isa; int i, j, ata33, ata66; + int bus_speed = system_bus_clock(); byte revision = 0; for (i = 0; i < arraysize (ApolloHostChipInfo) && !host_dev; i++) { @@ -873,18 +890,26 @@ ata33 = 1; ata66 = 0; + via82cxxx_table = ApolloISAChipInfo[j].chipset_table; + if (ApolloISAChipInfo[j].flags & VIA_FLAG_CHECK_REV) { pci_read_config_byte(isa_dev, 0x0d, &revision); ata33 = (revision >= 0x20) ? 1 : 0; } else if (ApolloISAChipInfo[j].flags & VIA_FLAG_ATA_66) { + byte ata66_0 = 0, ata66_1 = 0; ata33 = 0; ata66 = 1; + pci_read_config_byte(dev, 0x50, &ata66_1); + pci_read_config_byte(dev, 0x52, &ata66_0); + if ((ata66_0 & 0x04) || (ata66_1 & 0x04)) { + via82cxxx_table = (bus_speed == 33 || bus_speed == 37) ? + via82cxxx_type_four : + via82cxxx_type_three; + } } if (ata33 | ata66) printk(" Chipset Core ATA-%s", ata66 ? "66" : "33"); - - via82cxxx_table = ApolloISAChipInfo[j].chipset_table; } printk("\n"); } @@ -915,6 +940,7 @@ #ifdef CONFIG_VIA82CXXX_TUNING hwif->tuneproc = &via82cxxx_tune_drive; + hwif->speedproc = &via82cxxx_tune_chipset; hwif->drives[0].autotune = 1; hwif->drives[1].autotune = 1; hwif->autodma = 0; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/isdn/avmb1/kcapi.c linux/drivers/isdn/avmb1/kcapi.c --- v2.3.99-pre8/linux/drivers/isdn/avmb1/kcapi.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/isdn/avmb1/kcapi.c Sun May 21 20:18:08 2000 @@ -320,7 +320,7 @@ *eof = 1; if (off >= len+begin) return 0; - *start = page + (begin-off); + *start = page + (off-begin); return ((count < begin+len-off) ? count : begin+len-off); } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/macintosh/Makefile linux/drivers/macintosh/Makefile --- v2.3.99-pre8/linux/drivers/macintosh/Makefile Sun Feb 13 19:29:03 2000 +++ linux/drivers/macintosh/Makefile Sat May 20 12:07:56 2000 @@ -12,20 +12,20 @@ SUB_DIRS := MOD_SUB_DIRS := $(SUB_DIRS) -L_TARGET := macintosh.a -L_OBJS := +O_TARGET := macintosh.o +O_OBJS := M_OBJS := ifeq ($(CONFIG_PMAC_PBOOK),y) - L_OBJS += mediabay.o + O_OBJS += mediabay.o else ifeq ($(CONFIG_MAC_FLOPPY),y) - L_OBJS += mediabay.o + O_OBJS += mediabay.o endif endif ifeq ($(CONFIG_MAC_SERIAL),y) - L_OBJS += macserial.o + O_OBJS += macserial.o else ifeq ($(CONFIG_MAC_SERIAL),m) M_OBJS += macserial.o @@ -33,7 +33,7 @@ endif ifeq ($(CONFIG_NVRAM),y) - L_OBJS += nvram.o + O_OBJS += nvram.o else ifeq ($(CONFIG_NVRAM),m) M_OBJS += nvram.o @@ -41,39 +41,39 @@ endif ifdef CONFIG_ADB - LX_OBJS := adb.o + OX_OBJS := adb.o endif ifdef CONFIG_ADB_KEYBOARD - L_OBJS += mac_keyb.o + O_OBJS += mac_keyb.o endif ifdef CONFIG_ADB_MACII - L_OBJS += via-macii.o + O_OBJS += via-macii.o endif ifdef CONFIG_ADB_MACIISI - L_OBJS += via-maciisi.o + O_OBJS += via-maciisi.o endif ifdef CONFIG_ADB_CUDA - L_OBJS += via-cuda.o + O_OBJS += via-cuda.o endif ifdef CONFIG_ADB_IOP - L_OBJS += adb-iop.o + O_OBJS += adb-iop.o endif ifdef CONFIG_ADB_PMU - L_OBJS += via-pmu.o + O_OBJS += via-pmu.o endif ifdef CONFIG_ADB_PMU68K - L_OBJS += via-pmu68k.o + O_OBJS += via-pmu68k.o endif ifdef CONFIG_ADB_MACIO - L_OBJS += macio-adb.o + O_OBJS += macio-adb.o endif include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c --- v2.3.99-pre8/linux/drivers/macintosh/adb.c Wed Feb 16 17:03:52 2000 +++ linux/drivers/macintosh/adb.c Sat May 20 12:07:56 2000 @@ -72,6 +72,7 @@ struct adb_driver *adb_controller; struct notifier_block *adb_client_list = NULL; static int adb_got_sleep = 0; +static int adb_inited = 0; #ifdef CONFIG_PMAC_PBOOK static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when); @@ -213,6 +214,11 @@ return 0; #endif + /* xmon may do early-init */ + if (adb_inited) + return 0; + adb_inited = 1; + adb_controller = NULL; i = 0; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c --- v2.3.99-pre8/linux/drivers/macintosh/mac_keyb.c Sun Feb 13 19:29:03 2000 +++ linux/drivers/macintosh/mac_keyb.c Sat May 20 12:07:56 2000 @@ -16,7 +16,7 @@ * * - Standard 1 button mouse * - All standard Apple Extended protocol (handler ID 4) - * - mouseman and trackman mice & trackballs + * - mouseman and trackman mice & trackballs * - PowerBook Trackpad (default setup: enable tapping) * - MicroSpeed mouse & trackball (needs testing) * - CH Products Trackball Pro (needs testing) @@ -344,7 +344,7 @@ #ifdef CONFIG_ADBMOUSE /* * XXX: Add mouse button 2+3 fake codes here if mouse open. - * Keep track of 'button' states here as we only send + * Keep track of 'button' states here as we only send * single up/down events! * Really messy; might need to check if keyboard is in * VC_RAW mode. @@ -591,11 +591,12 @@ static void buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll) { +#ifdef CONFIG_ADB_PMU /* * XXX: Where is the contrast control for the passive? * -- Cort */ - + /* Ignore data from register other than 0 */ #if 0 if ((adb_hardware != ADB_VIAPMU) || (data[0] & 0x3) || (nb < 2)) @@ -603,7 +604,7 @@ if ((data[0] & 0x3) || (nb < 2)) #endif return; - + switch (data[1]&0xf ) { /* mute */ @@ -627,28 +628,25 @@ /* brightness decrease */ case 0xa: /* down event */ -#ifdef CONFIG_PPC if ( data[1] == (data[1]&0xf) ) { if (backlight_level > 2) pmu_set_brightness(backlight_level-2); else pmu_set_brightness(0); } -#endif break; /* brightness increase */ case 0x9: /* down event */ -#ifdef CONFIG_PPC if ( data[1] == (data[1]&0xf) ) { if (backlight_level < 0x1e) pmu_set_brightness(backlight_level+2); - else + else pmu_set_brightness(0x1f); } -#endif break; } +#endif /* CONFIG_ADB_PMU */ } /* Map led flags as defined in kbd_kern.h to bits for Apple keyboard. */ @@ -736,7 +734,7 @@ led_request.complete = 1; mackeyb_probe(); - + notifier_chain_register(&adb_client_list, &mackeyb_adb_notifier); } @@ -744,11 +742,11 @@ adb_message_handler(struct notifier_block *this, unsigned long code, void *x) { unsigned long flags; - + switch (code) { case ADB_MSG_PRE_RESET: case ADB_MSG_POWERDOWN: - /* Stop the repeat timer. Autopoll is already off at this point */ + /* Stop the repeat timer. Autopoll is already off at this point */ save_flags(flags); cli(); del_timer(&repeat_timer); @@ -758,7 +756,7 @@ while(!led_request.complete) adb_poll(); break; - + case ADB_MSG_POST_RESET: mackeyb_probe(); break; @@ -841,7 +839,7 @@ || (adb_mouse_kinds[id] == ADBMOUSE_MICROSPEED)) { init_microspeed(id); } else if (adb_mouse_kinds[id] == ADBMOUSE_MS_A3) { - init_ms_a3(id); + init_ms_a3(id); } else if (adb_mouse_kinds[id] == ADBMOUSE_EXTENDED) { /* * Register 1 is usually used for device @@ -854,7 +852,7 @@ if ((req.reply_len) && (req.reply[1] == 0x9a) && ((req.reply[2] == 0x21) - || (req.reply[2] == 0x20))) + || (req.reply[2] == 0x20))) init_trackball(id); else if ((req.reply_len >= 4) && (req.reply[1] == 0x74) && (req.reply[2] == 0x70) && @@ -877,10 +875,10 @@ } } -static void +static void init_trackpad(int id) { - struct adb_request req; + struct adb_request req; unsigned char r1_buffer[8]; printk(" (trackpad)"); @@ -907,15 +905,15 @@ adb_request(&req, NULL, ADBREQ_SYNC, 9, ADB_WRITEREG(id,2), - 0x99, - 0x94, - 0x19, - 0xff, - 0xb2, - 0x8a, - 0x1b, - 0x50); - + 0x99, + 0x94, + 0x19, + 0xff, + 0xb2, + 0x8a, + 0x1b, + 0x50); + adb_request(&req, NULL, ADBREQ_SYNC, 9, ADB_WRITEREG(id,1), r1_buffer[0], @@ -929,13 +927,13 @@ } } -static void +static void init_trackball(int id) { struct adb_request req; - + printk(" (trackman/mouseman)"); - + adb_mouse_kinds[id] = ADBMOUSE_TRACKBALL; adb_request(&req, NULL, ADBREQ_SYNC, 3, @@ -971,7 +969,7 @@ printk(" (TurboMouse 5)"); adb_mouse_kinds[id] = ADBMOUSE_TURBOMOUSE5; - + adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(3)); @@ -1012,7 +1010,7 @@ /* This will initialize mice using the Microspeed, MacPoint and other compatible firmware. Bit 12 enables extended protocol. - + Register 1 Listen (4 Bytes) 0 - 3 Button is mouse (set also for double clicking!!!) 4 - 7 Button is locking (affects change speed also) @@ -1027,7 +1025,7 @@ 0 - 7 Product code 8 - 23 undefined, reserved 24 - 31 Version number - + Speed 0 is max. 1 to 255 set speed in increments of 1/256 of max. */ adb_request(&req, NULL, ADBREQ_SYNC, 5, @@ -1051,7 +1049,7 @@ ADB_WRITEREG(id, 0x2), 0x00, 0x07); - + adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id)); } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c --- v2.3.99-pre8/linux/drivers/macintosh/macserial.c Sun Feb 13 19:29:03 2000 +++ linux/drivers/macintosh/macserial.c Sat May 20 12:07:56 2000 @@ -131,17 +131,17 @@ #define _INLINE_ inline #ifdef SERIAL_DEBUG_OPEN -#define OPNDBG(fmt, arg...) printk(KERN_INFO fmt , ## arg) +#define OPNDBG(fmt, arg...) printk(KERN_DEBUG fmt , ## arg) #else #define OPNDBG(fmt, arg...) do { } while (0) #endif #ifdef SERIAL_DEBUG_POWER -#define PWRDBG(fmt, arg...) printk(KERN_INFO fmt , ## arg) +#define PWRDBG(fmt, arg...) printk(KERN_DEBUG fmt , ## arg) #else #define PWRDBG(fmt, arg...) do { } while (0) #endif #ifdef SERIAL_DEBUG_BAUDS -#define BAUDBG(fmt, arg...) printk(KERN_INFO fmt , ## arg) +#define BAUDBG(fmt, arg...) printk(fmt , ## arg) #else #define BAUDBG(fmt, arg...) do { } while (0) #endif @@ -414,7 +414,7 @@ continue; if (tty->flip.count >= TTY_FLIPBUF_SIZE) tty_flip_buffer_push(tty); - + if (tty->flip.count >= TTY_FLIPBUF_SIZE) { static int flip_buf_ovf; if (++flip_buf_ovf <= 1) @@ -505,7 +505,7 @@ if (info->tx_stopped) { #ifdef SERIAL_DEBUG_FLOW printk("CTS up\n"); -#endif +#endif info->tx_stopped = 0; if (!info->tx_active) transmit_chars(info); @@ -513,7 +513,7 @@ } else { #ifdef SERIAL_DEBUG_FLOW printk("CTS down\n"); -#endif +#endif info->tx_stopped = 1; } } @@ -536,7 +536,7 @@ == virt_to_bus(info->rx_cmds[info->rx_cbuf] + 1)) where -= in_le16(&info->rx->res_count); where--; - + stat = read_zsreg(info->zs_channel, R1); flag = stat_to_flag(stat); @@ -582,7 +582,7 @@ #ifdef SERIAL_DEBUG_INTR printk("rs_interrupt: irq %d, zs_intreg 0x%x\n", irq, (int)zs_intreg); -#endif +#endif if ((zs_intreg & CHAN_IRQMASK) == 0) break; @@ -659,7 +659,7 @@ if (serial_paranoia_check(info, tty->device, "rs_stop")) return; - + #if 0 save_flags(flags); cli(); if (info->curregs[5] & TxENAB) { @@ -675,7 +675,7 @@ { struct mac_serial *info = (struct mac_serial *)tty->driver_data; unsigned long flags; - + #ifdef SERIAL_DEBUG_STOP printk("rs_start %ld....\n", tty->ldisc.chars_in_buffer(tty)); @@ -683,7 +683,7 @@ if (serial_paranoia_check(info, tty->device, "rs_start")) return; - + save_flags(flags); cli(); #if 0 if (info->xmit_cnt && info->xmit_buf && !(info->curregs[5] & TxENAB)) { @@ -717,7 +717,7 @@ { struct mac_serial *info = (struct mac_serial *) private_; struct tty_struct *tty; - + tty = info->tty; if (!tty) return; @@ -750,7 +750,7 @@ OPNDBG("starting up ttyS%d (irq %d)...\n", info->line, info->irq); delay = set_scc_power(info, 1); - + setup_scc(info); OPNDBG("enabling IRQ on ttyS%d (irq %d)...\n", info->line, info->irq); @@ -758,7 +758,6 @@ info->flags |= ZILOG_INITIALIZED; enable_irq(info->irq); if (info->dma_initted) { -// enable_irq(info->tx_dma_irq); enable_irq(info->rx_dma_irq); } @@ -881,8 +880,6 @@ volatile struct dbdma_cmd *cd; unsigned char *p; -//printk(KERN_DEBUG "SCC: dma_init\n"); - info->rx_nbuf = 8; /* various mem set up */ @@ -958,10 +955,10 @@ static int setup_scc(struct mac_serial * info) { unsigned long flags; - + OPNDBG("setting up ttys%d SCC...\n", info->line); - save_flags(flags); cli(); /* Disable interrupts */ + save_flags(flags); cli(); /* Disable interrupts */ /* * Reset the chip. @@ -992,7 +989,8 @@ /* * Turn on RTS and DTR. */ - zs_rtsdtr(info, 1); + if (!info->is_irda) + zs_rtsdtr(info, 1); /* * Finally, enable sequencing and interrupts @@ -1058,7 +1056,7 @@ { OPNDBG("Shutting down serial port %d (irq %d)....\n", info->line, info->irq); - + if (!(info->flags & ZILOG_INITIALIZED)) { OPNDBG("(already shutdown)\n"); return; @@ -1124,7 +1122,7 @@ /* The timings looks strange but that's the ones MacOS seems to use for the internal modem. I think we can use a lot faster ones, at least whe not using the modem, this should be tested. - */ + */ if (state) { PWRDBG("ttyS%02d: powering up hardware\n", info->line); if (feature_test(info->dev_node, FEATURE_Serial_enable) == 0) { @@ -1150,7 +1148,7 @@ delay = 2500; /* wait for 2.5s before using */ } #ifdef CONFIG_PMAC_PBOOK - if (info->is_pwbk_ir) + if (info->is_irda) pmu_enable_irled(1); #endif /* CONFIG_PMAC_PBOOK */ } else { @@ -1161,14 +1159,14 @@ mdelay(10); } #ifdef CONFIG_PMAC_PBOOK - if (info->is_pwbk_ir) + if (info->is_irda) pmu_enable_irled(0); #endif /* CONFIG_PMAC_PBOOK */ - - if (info->zs_chan_a == info->zs_channel) { + + if (info->zs_chan_a == info->zs_channel && !info->is_irda) { PWRDBG("ttyS%02d: shutting down SCC channel A\n", info->line); feature_clear(info->dev_node, FEATURE_Serial_IO_A); - } else { + } else if (!info->is_irda) { PWRDBG("ttyS%02d: shutting down SCC channel B\n", info->line); feature_clear(info->dev_node, FEATURE_Serial_IO_B); } @@ -1188,6 +1186,113 @@ return delay; } +static void irda_rts_pulses(struct mac_serial *info, int w) +{ + unsigned long flags; + + udelay(w); + save_flags(flags); cli(); + write_zsreg(info->zs_channel, 5, Tx8 | TxENAB); + udelay(2); + write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS); + udelay(8); + write_zsreg(info->zs_channel, 5, Tx8 | TxENAB); + udelay(4); + write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS); + restore_flags(flags); +} + +/* + * Set the irda codec on the imac to the specified baud rate. + */ +static void irda_setup(struct mac_serial *info) +{ + int code, speed, t; + unsigned long flags; + + speed = info->tty->termios->c_cflag & CBAUD; + if (speed < B2400 || speed > B115200) + return; + code = 0x4d + B115200 - speed; + + /* disable serial interrupts and receive DMA */ + write_zsreg(info->zs_channel, 1, info->curregs[1] & ~0x9f); + + /* wait for transmitter to drain */ + t = 10000; + while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0 + || (read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) { + if (--t <= 0) { + printk(KERN_ERR "transmitter didn't drain\n"); + return; + } + udelay(10); + } + udelay(100); + + /* set to 8 bits, no parity, 19200 baud, RTS on, DTR off */ + write_zsreg(info->zs_channel, 4, X16CLK | SB1); + write_zsreg(info->zs_channel, 11, TCBR | RCBR); + t = BPS_TO_BRG(19200, ZS_CLOCK/16); + write_zsreg(info->zs_channel, 12, t); + write_zsreg(info->zs_channel, 13, t >> 8); + write_zsreg(info->zs_channel, 14, BRENABL); + write_zsreg(info->zs_channel, 3, Rx8 | RxENABLE); + write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS); + + /* set TxD low for ~104us and pulse RTS */ + udelay(1000); + save_flags(flags); cli(); + write_zsdata(info->zs_channel, 0xfe); + irda_rts_pulses(info, 150); + restore_flags(flags); + irda_rts_pulses(info, 180); + irda_rts_pulses(info, 50); + udelay(100); + + /* assert DTR, wait 30ms, talk to the chip */ + write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS | DTR); + udelay(30000); + while (read_zsreg(info->zs_channel, 0) & Rx_CH_AV) + read_zsdata(info->zs_channel); + + write_zsdata(info->zs_channel, 1); + t = 1000; + while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) { + if (--t <= 0) { + printk(KERN_ERR "irda_setup timed out on 1st byte\n"); + goto out; + } + udelay(10); + } + t = read_zsdata(info->zs_channel); + if (t != 4) + printk(KERN_ERR "irda_setup 1st byte = %x\n", t); + + write_zsdata(info->zs_channel, code); + t = 1000; + while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) { + if (--t <= 0) { + printk(KERN_ERR "irda_setup timed out on 2nd byte\n"); + goto out; + } + udelay(10); + } + t = read_zsdata(info->zs_channel); + if (t != code) + printk(KERN_ERR "irda_setup 2nd byte = %x (%x)\n", t, code); + + /* Drop DTR again and do some more RTS pulses */ + out: + udelay(100); + write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS); + irda_rts_pulses(info, 80); + + /* We should be right to go now. We assume that load_zsregs + will get called soon to load up the correct baud rate etc. */ + info->curregs[5] = (info->curregs[5] | RTS) & ~DTR; + info->pendregs[5] = info->curregs[5]; +} /* * This routine is called to set the UART divisor registers to match @@ -1195,7 +1300,6 @@ */ static void change_speed(struct mac_serial *info, struct termios *old_termios) { - unsigned short port; unsigned cflag; int bits; int brg, baud; @@ -1203,8 +1307,6 @@ if (!info->tty || !info->tty->termios) return; - if (!(port = info->port)) - return; cflag = info->tty->termios->c_cflag; baud = tty_get_baud_rate(info->tty); @@ -1227,7 +1329,7 @@ info->zs_baud = baud; info->clk_divisor = 16; - BAUDBG("set speed to %d bds, ", baud); + BAUDBG(KERN_DEBUG "set speed to %d bds, ", baud); switch (baud) { case ZS_CLOCK/16: /* 230400 */ @@ -1325,6 +1427,10 @@ BAUDBG("timeout=%d/%ds, base:%d\n", (int)info->timeout, (int)HZ, (int)info->baud_base); + /* set the irda codec to the right rate */ + if (info->is_irda) + irda_setup(info); + /* Load up the new values */ load_zsregs(info->zs_channel, info->curregs); @@ -1391,7 +1497,7 @@ } else { while (1) { save_flags(flags); - cli(); + cli(); c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); @@ -1419,7 +1525,7 @@ { struct mac_serial *info = (struct mac_serial *)tty->driver_data; int ret; - + if (serial_paranoia_check(info, tty->device, "rs_write_room")) return 0; ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; @@ -1431,7 +1537,7 @@ static int rs_chars_in_buffer(struct tty_struct *tty) { struct mac_serial *info = (struct mac_serial *)tty->driver_data; - + if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer")) return 0; return info->xmit_cnt; @@ -1441,7 +1547,7 @@ { struct mac_serial *info = (struct mac_serial *)tty->driver_data; unsigned long flags; - + if (serial_paranoia_check(info, tty->device, "rs_flush_buffer")) return; save_flags(flags); cli(); @@ -1466,13 +1572,12 @@ struct mac_serial *info = (struct mac_serial *)tty->driver_data; unsigned long flags; #ifdef SERIAL_DEBUG_THROTTLE - printk("throttle %ld....\n",tty->ldisc.chars_in_buffer(tty)); #endif if (serial_paranoia_check(info, tty->device, "rs_throttle")) return; - + if (I_IXOFF(tty)) { save_flags(flags); cli(); info->x_char = STOP_CHAR(tty); @@ -1502,13 +1607,12 @@ struct mac_serial *info = (struct mac_serial *)tty->driver_data; unsigned long flags; #ifdef SERIAL_DEBUG_THROTTLE - printk("unthrottle %s: %d....\n",tty->ldisc.chars_in_buffer(tty)); #endif if (serial_paranoia_check(info, tty->device, "rs_unthrottle")) return; - + if (I_IXOFF(tty)) { save_flags(flags); cli(); if (info->x_char) @@ -1685,8 +1789,6 @@ if (serial_paranoia_check(info, tty->device, "rs_break")) return; - if (!info->port) - return; save_flags(flags); cli(); if (break_state == -1) @@ -1714,7 +1816,7 @@ if (tty->flags & (1 << TTY_IO_ERROR)) return -EIO; } - + switch (cmd) { case TIOCMGET: return get_modem_info(info, (unsigned int *) arg); @@ -1736,7 +1838,7 @@ info, sizeof(struct mac_serial))) return -EFAULT; return 0; - + default: return -ENOIOCTLCMD; } @@ -1775,15 +1877,15 @@ if (!info || serial_paranoia_check(info, tty->device, "rs_close")) return; - + save_flags(flags); cli(); - + if (tty_hung_up_p(filp)) { MOD_DEC_USE_COUNT; restore_flags(flags); return; } - + OPNDBG("rs_close ttys%d, count = %d\n", info->line, info->count); if ((tty->count == 1) && (info->count != 1)) { /* @@ -1984,7 +2086,7 @@ info->flags |= ZILOG_CALLOUT_ACTIVE; return 0; } - + /* * If non-blocking mode is set, or the port is not enabled, * then make the check up front and then exit. @@ -2004,7 +2106,7 @@ if (tty->termios->c_cflag & CLOCAL) do_clocal = 1; } - + /* * Block waiting for the carrier detect and the line to become * free (i.e., not in use by the callout). While we are in @@ -2024,7 +2126,8 @@ while (1) { cli(); if (!(info->flags & ZILOG_CALLOUT_ACTIVE) && - (tty->termios->c_cflag & CBAUD)) + (tty->termios->c_cflag & CBAUD) && + !info->is_irda) zs_rtsdtr(info, 1); sti(); set_current_state(TASK_INTERRUPTIBLE); @@ -2034,7 +2137,7 @@ if (info->flags & ZILOG_HUP_NOTIFY) retval = -EAGAIN; else - retval = -ERESTARTSYS; + retval = -ERESTARTSYS; #else retval = -EAGAIN; #endif @@ -2063,7 +2166,7 @@ return retval; info->flags |= ZILOG_NORMAL_ACTIVE; return 0; -} +} /* * This routine is called whenever a serial port is opened. It @@ -2208,11 +2311,11 @@ /* XXX tested only with wallstreet PowerBook, should do no harm anyway */ conn = get_property(ch, "AAPL,connector", &len); - zss->is_pwbk_ir = conn && (strcmp(conn, "infrared") == 0); + zss->is_irda = conn && (strcmp(conn, "infrared") == 0); /* 1999 Powerbook G3 has slot-names property instead */ slots = (struct slot_names_prop *)get_property(ch, "slot-names", &len); if (slots && slots->count > 0 && strcmp(slots->name, "IrDA") == 0) - zss->is_pwbk_ir = 1; + zss->is_irda = 1; if (zss->has_dma) { zss->dma_priv = NULL; @@ -2345,7 +2448,11 @@ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; +#ifdef CONFIG_DEVFS_FS + serial_driver.name = "tts/%d"; +#else serial_driver.name = "ttyS"; +#endif /* CONFIG_DEVFS_FS */ serial_driver.major = TTY_MAJOR; serial_driver.minor_start = 64; serial_driver.num = zs_channels_found; @@ -2383,7 +2490,11 @@ * major number and the subtype code. */ callout_driver = serial_driver; +#ifdef CONFIG_DEVFS_FS + callout_driver.name = "cua/%d"; +#else callout_driver.name = "cua"; +#endif /* CONFIG_DEVFS_FS */ callout_driver.major = TTYAUX_MAJOR; callout_driver.subtype = SERIAL_TYPE_CALLOUT; @@ -2402,7 +2513,7 @@ zs_soft[channel].clk_divisor = 16; /* -- we are not sure the SCC is powered ON at this point zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]); -*/ +*/ zs_soft[channel].zs_baud = 38400; /* If console serial line, then enable interrupts. */ @@ -2453,16 +2564,16 @@ printk(", port = %s", connector); if (info->is_cobalt_modem) printk(" (cobalt modem)"); - if (info->is_pwbk_ir) - printk(" (powerbook IR)"); + if (info->is_irda) + printk(" (IrDA)"); printk("\n"); #ifndef CONFIG_XMON #ifdef CONFIG_KGDB if (!info->kgdb_channel) #endif /* CONFIG_KGDB */ - /* By default, disable the port */ - set_scc_power(info, 0); + /* By default, disable the port */ + set_scc_power(info, 0); #endif /* CONFIG_XMON */ } tmp_buf = 0; @@ -2561,7 +2672,7 @@ while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0) eieio(); - + write_zsdata(info->zs_channel, 13); } } @@ -2869,7 +2980,7 @@ probe_sccs(); set_scc_power(&zs_soft[tty_num], 1); - + zs_kgdbchan = zs_soft[tty_num].zs_channel; zs_soft[tty_num].change_needed = 0; zs_soft[tty_num].clk_divisor = 16; @@ -2891,12 +3002,12 @@ serial_notify_sleep(struct pmu_sleep_notifier *self, int when) { int i; - + switch (when) { case PBOOK_SLEEP_REQUEST: case PBOOK_SLEEP_REJECT: break; - + case PBOOK_SLEEP_NOW: for (i=0; icontents) >> 4) & 7) +inline int mb_content(volatile struct media_bay_info *bay) +{ + if (bay->pismo) { + unsigned char new_gpio = in_8(bay->extint_gpio + 0xe) & 2; + if (new_gpio) { + bay->gpio_cache = new_gpio; + return MB_NO; + } else if (bay->gpio_cache != new_gpio) { + /* make sure content bits are set */ + feature_set(bay->dev_node, FEATURE_Mediabay_content); + udelay(5); + bay->gpio_cache = new_gpio; + } + return (in_le32((unsigned*)bay->addr) >> 4) & 0xf; + } else { + int cont = (in_8(&bay->addr->contents) >> 4) & 7; + return (cont == 7) ? MB_NO : cont; + } +} #ifdef CONFIG_BLK_DEV_IDE /* check the busy bit in the media-bay ide interface @@ -184,12 +207,22 @@ media_bays[n].addr = (volatile struct media_bay_hw *) ioremap(np->addrs[0].address, sizeof(struct media_bay_hw)); + media_bays[n].pismo = device_is_compatible(np, "keylargo-media-bay"); + if (media_bays[n].pismo) { + if (!np->parent || strcmp(np->parent->name, "mac-io")) { + printk(KERN_ERR "Pismo media-bay has no mac-io parent !\n"); + continue; + } + media_bays[n].extint_gpio = ioremap(np->parent->addrs[0].address + + 0x58, 0x10); + } + #ifdef MB_USE_INTERRUPTS if (np->n_intrs == 0) { printk(KERN_ERR "media bay %d has no irq\n",n); continue; } - + if (request_irq(np->intrs[0].line, media_bay_intr, 0, "Media bay", (void *)n)) { printk(KERN_ERR "Couldn't get IRQ %d for media bay %d\n", np->intrs[0].line, n); @@ -203,10 +236,11 @@ /* Force an immediate detect */ set_mb_power(n,0); mdelay(MB_POWER_DELAY); - out_8(&media_bays[n].addr->contents, 0x70); + if(!media_bays[n].pismo) + out_8(&media_bays[n].addr->contents, 0x70); mdelay(MB_STABLE_DELAY); media_bays[n].content_id = MB_NO; - media_bays[n].last_value = MB_CONTENTS(n); + media_bays[n].last_value = mb_content(&media_bays[n]); media_bays[n].value_count = MS_TO_HZ(MB_STABLE_DELAY); media_bays[n].state = mb_empty; do { @@ -214,11 +248,11 @@ media_bay_step(n); } while((media_bays[n].state != mb_empty) && (media_bays[n].state != mb_up)); - + n++; np=np->next; } - + if (media_bay_count) { printk(KERN_INFO "Registered %d media-bay(s)\n", media_bay_count); @@ -227,7 +261,8 @@ pmu_register_sleep_notifier(&mb_sleep_notifier); #endif /* CONFIG_PMAC_PBOOK */ - kernel_thread(media_bay_task, NULL, 0); + kernel_thread(media_bay_task, NULL, + CLONE_FS | CLONE_FILES | CLONE_SIGHAND); } } @@ -252,7 +287,11 @@ MBDBG("mediabay%d: powering up\n", which); } else { feature_clear(mb->dev_node, FEATURE_Mediabay_floppy_enable); - feature_clear(mb->dev_node, FEATURE_IDE1_enable); + if (mb->pismo) + feature_clear(mb->dev_node, FEATURE_IDE0_enable); + else + feature_clear(mb->dev_node, FEATURE_IDE1_enable); + feature_clear(mb->dev_node, FEATURE_Mediabay_IDE_switch); feature_clear(mb->dev_node, FEATURE_Mediabay_PCI_enable); feature_clear(mb->dev_node, FEATURE_SWIM3_enable); feature_clear(mb->dev_node, FEATURE_Mediabay_power); @@ -271,9 +310,17 @@ switch (id) { case MB_CD: - feature_set(bay->dev_node, FEATURE_IDE1_enable); - udelay(10); - feature_set(bay->dev_node, FEATURE_IDE1_reset); + if (bay->pismo) { + feature_set(bay->dev_node, FEATURE_Mediabay_IDE_switch); + udelay(10); + feature_set(bay->dev_node, FEATURE_IDE0_enable); + udelay(10); + feature_set(bay->dev_node, FEATURE_IDE0_reset); + } else { + feature_set(bay->dev_node, FEATURE_IDE1_enable); + udelay(10); + feature_set(bay->dev_node, FEATURE_IDE1_reset); + } printk(KERN_INFO "media bay %d contains a CD-ROM drive\n", which); break; case MB_FD: @@ -345,8 +392,8 @@ if ((MB_CD != media_bays[i].content_id) || media_bays[i].state != mb_up) return 0; - - printk(KERN_DEBUG "Registered ide %d for media bay %d\n", index, i); + + printk(KERN_DEBUG "Registered ide %d for media bay %d\n", index, i); do { if (MB_IDE_READY(i)) { media_bays[i].cd_index = index; @@ -354,7 +401,7 @@ } mdelay(1); } while(--timeout); - printk(KERN_DEBUG "Timeout waiting IDE in bay %d\n", i); + printk(KERN_DEBUG "Timeount waiting IDE in bay %d\n", i); return -ENODEV; } #endif @@ -397,7 +444,10 @@ } #ifdef CONFIG_BLK_DEV_IDE MBDBG("mediabay%d: waiting IDE reset (kind:%d)\n", i, bay->content_id); - feature_clear(bay->dev_node, FEATURE_IDE1_reset); + if (bay->pismo) + feature_clear(bay->dev_node, FEATURE_IDE0_reset); + else + feature_clear(bay->dev_node, FEATURE_IDE1_reset); bay->timer = MS_TO_HZ(MB_IDE_WAIT); bay->state = mb_ide_resetting; #else @@ -476,23 +526,21 @@ int __pmac media_bay_task(void *x) { - int i = 0; - + int i; + strcpy(current->comm, "media-bay"); #ifdef MB_IGNORE_SIGNALS sigfillset(¤t->blocked); #endif for (;;) { - media_bay_step(i); + for (i = 0; i < media_bay_count; ++i) + media_bay_step(i); - if (++i >= media_bay_count) { - i = 0; current->state = TASK_INTERRUPTIBLE; schedule_timeout(1); if (signal_pending(current)) return 0; - } } } @@ -500,7 +548,7 @@ poll_media_bay(int which) { volatile struct media_bay_info* bay = &media_bays[which]; - int id = MB_CONTENTS(which); + int id = mb_content(bay); if (id == bay->last_value) { if (id != bay->content_id @@ -548,27 +596,26 @@ bay = &media_bays[i]; set_mb_power(i, 0); mdelay(10); - out_8(&bay->addr->contents, 0x70); } break; case PBOOK_WAKE: for (i=0; iaddr->contents, 0x70); + if (!bay->pismo) + out_8(&bay->addr->contents, 0x70); mdelay(MB_STABLE_DELAY); - if (MB_CONTENTS(i) != bay->content_id) + if (mb_content(bay) != bay->content_id) continue; set_mb_power(i, 1); - mdelay(MB_POWER_DELAY); - media_bays[i].last_value = bay->content_id; - media_bays[i].value_count = MS_TO_HZ(MB_STABLE_DELAY); - media_bays[i].timer = 0; - media_bays[i].cd_retry = 0; + bay->last_value = bay->content_id; + bay->value_count = MS_TO_HZ(MB_STABLE_DELAY); + bay->timer = MS_TO_HZ(MB_POWER_DELAY); + bay->cd_retry = 0; do { mdelay(1000/HZ); media_bay_step(i); @@ -580,3 +627,4 @@ return PBOOK_SLEEP_OK; } #endif /* CONFIG_PMAC_PBOOK */ + diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/macintosh/nvram.c linux/drivers/macintosh/nvram.c --- v2.3.99-pre8/linux/drivers/macintosh/nvram.c Thu Feb 10 17:11:09 2000 +++ linux/drivers/macintosh/nvram.c Sat May 20 12:07:56 2000 @@ -96,21 +96,18 @@ &nvram_fops }; -int nvram_init(void) +int __init nvram_init(void) { printk(KERN_INFO "Macintosh non-volatile memory driver v%s\n", NVRAM_VERSION); misc_register(&nvram_dev); return 0; } -#ifdef MODULE -int init_module (void) -{ - return( nvram_init() ); -} -void cleanup_module (void) +void __exit nvram_cleanup(void) { misc_deregister( &nvram_dev ); } -#endif + +module_init(nvram_init); +module_exit(nvram_cleanup); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c --- v2.3.99-pre8/linux/drivers/macintosh/via-pmu.c Thu Feb 10 17:11:09 2000 +++ linux/drivers/macintosh/via-pmu.c Sat May 20 12:07:56 2000 @@ -41,6 +41,7 @@ #include #include #include +#include /* Misc minor number allocated for /dev/pmu */ #define PMU_MINOR 154 @@ -201,7 +202,7 @@ "PowerBook 2400/3400/3500(G3)", "PowerBook G3 Series", "1999 PowerBook G3", - "Core99 (iBook/iMac/G4)" + "Core99" }; int __openfirmware @@ -326,7 +327,7 @@ out_8(&via[IER], IER_SET | SR_INT | CB1_INT); pmu_fully_inited = 1; - + /* Enable backlight */ pmu_enable_backlight(1); } @@ -508,7 +509,7 @@ if (save_autopoll != 0) pmu_adb_autopoll(save_autopoll); - + return 0; } @@ -845,9 +846,9 @@ } else { #ifdef CONFIG_XMON if (len == 4 && data[1] == 0x2c) { - extern int xmon_wants_key, xmon_pmu_keycode; + extern int xmon_wants_key, xmon_adb_keycode; if (xmon_wants_key) { - xmon_pmu_keycode = data[2]; + xmon_adb_keycode = data[2]; return; } } @@ -886,7 +887,7 @@ if ((vias == NULL) || !pmu_has_backlight) return; - + /* first call: get current backlight value */ if (on && backlight_level < 0) { switch (pmu_kind) { @@ -983,12 +984,12 @@ struct adb_request req; cli(); - + pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB | PMU_INT_TICK ); while(!req.complete) pmu_poll(); - + pmu_request(&req, NULL, 1, PMU_RESET); while(!req.complete || (pmu_state != idle)) pmu_poll(); @@ -1002,7 +1003,7 @@ struct adb_request req; cli(); - + pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB | PMU_INT_TICK ); while(!req.complete) @@ -1065,6 +1066,8 @@ current = list_entry(list, struct pmu_sleep_notifier, list); ret = current->notifier_call(current, when); if (ret != PBOOK_SLEEP_OK) { + printk(KERN_DEBUG "sleep %d rejected by %p (%p)\n", + when, current, current->notifier_call); for (; list != &sleep_notifiers; list = list->next) { current = list_entry(list, struct pmu_sleep_notifier, list); current->notifier_call(current, fallback); @@ -1179,7 +1182,7 @@ while (!req.complete) pmu_poll(); udelay(50000); } - udelay(50000); + udelay(150000); } #endif @@ -1240,20 +1243,14 @@ /* Make sure the decrementer won't interrupt us */ asm volatile("mtdec %0" : : "r" (0x7fffffff)); -#if 0 - /* Save the state of PCI config space for some slots */ - pbook_pci_save(); -#endif + /* For 750, save backside cache setting and disable it */ save_l2cr = _get_L2CR(); /* (returns 0 if not 750) */ if (save_l2cr) _set_L2CR(0); - if (macio_base != 0) { + if (macio_base != 0) save_fcr = in_le32(FEATURE_CTRL(macio_base)); - /* Check if this is still valid on older powerbooks */ - out_le32(FEATURE_CTRL(macio_base), save_fcr & ~(0x00000140UL)); - } if (current->thread.regs && (current->thread.regs->msr & MSR_FP) != 0) giveup_fpu(current); @@ -1267,12 +1264,15 @@ /* Ask the PMU to put us to sleep */ pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T'); while (!sleep_req.complete) - mb(); + pmu_poll(); cli(); while (pmu_state != idle) pmu_poll(); + /* clear IOBUS enable */ + out_le32(FEATURE_CTRL(macio_base), save_fcr & ~HRW_IOBUS_ENABLE); + /* Call low-level ASM sleep handler */ low_sleep_handler(); @@ -1281,17 +1281,15 @@ pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP); grackle_pcibios_write_config_word(0, 0, 0x70, pmcr1); + /* reenable IOBUS */ + out_le32(FEATURE_CTRL(macio_base), save_fcr | HRW_IOBUS_ENABLE); + /* Make sure the PMU is idle */ while (pmu_state != idle) pmu_poll(); sti(); -#if 0 - /* According to someone from Apple, this should not be needed, - at least not for all devices. Let's keep it for now until we - have something that works. */ - pbook_pci_restore(); -#endif + set_context(current->mm->context); /* Restore L2 cache */ @@ -1302,6 +1300,7 @@ sleep_restore_intrs(); /* Notify drivers */ + mdelay(10); broadcast_wake(); return 0; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c --- v2.3.99-pre8/linux/drivers/net/3c59x.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/3c59x.c Sat May 13 08:19:21 2000 @@ -423,7 +423,7 @@ { 0x10B7, 0x6560, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE656 }, { 0x10B7, 0x6562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656 }, { 0x10B7, 0x4500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C450 }, - {0,}, /* 0 terminated list. */ + {0,} /* 0 terminated list. */ }; MODULE_DEVICE_TABLE(pci, vortex_pci_tbl); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/8139too.c linux/drivers/net/8139too.c --- v2.3.99-pre8/linux/drivers/net/8139too.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/8139too.c Sat May 20 11:38:03 2000 @@ -24,6 +24,15 @@ Daniel Kobras - identified specific locations of posted MMIO write bugginess + Gerard Sharp - bug fix + + Submitting bug reports: + + "rtl8139-diag -mmmaaavvveefN" output + enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log + + See 8139too.txt for more details. + ----------------------------------------------------------------------------- Theory of Operation @@ -88,7 +97,7 @@ #include -#define RTL8139_VERSION "0.9.4.1" +#define RTL8139_VERSION "0.9.5" #define RTL8139_MODULE_NAME "8139too" #define RTL8139_DRIVER_NAME RTL8139_MODULE_NAME " Fast Ethernet driver " RTL8139_VERSION #define PFX RTL8139_MODULE_NAME ": " @@ -201,7 +210,7 @@ /* {0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MPX5030 },*/ {0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DELTA8139 }, {0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 }, - {0,}, + {0,} }; MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl); @@ -304,6 +313,17 @@ AcceptAllPhys = 0x01, }; +/* Bits in TxConfig. */ +enum tx_config_bits { + TxIFG1 = (1 << 25), /* Interframe Gap Time */ + TxIFG0 = (1 << 24), /* Enabling these bits violates IEEE 802.3 */ + TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */ + TxCRC = (1 << 16), /* DISABLE appending CRC to end of Tx packets */ + TxClearAbt = (1 << 0), /* Clear abort (WO) */ + + TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */ +}; + /* Bits in Config1 */ enum Config1Bits { Cfg1_PM_Enable = 0x01, @@ -369,28 +389,53 @@ dma_addr_t mapping; }; + typedef enum { CH_8139 = 0, CH_8139A, + CH_8139A_G, CH_8139B, + CH_8130, + CH_8139C, } chip_t; + /* directly indexed by chip_t, above */ const static struct { const char *name; + u32 version; /* from RTL8139C docs */ u32 RxConfigMask; /* should clear the bits supported by this chip */ } rtl_chip_info[] = { { "RTL-8139", + 0x60000000, 0xf0fe0040, /* XXX copied from RTL8139A, verify */ }, { "RTL-8139A", + 0x70000000, 0xf0fe0040, }, - { "RTL-8139B(L)", + { "RTL-8139A rev. G", + 0x70800000, + 0xf0fe0040, + }, + + { "RTL-8139B", + 0x78000000, 0xf0fc0040 }, + + { "RTL-8130", + 0x7C000000, + 0xf0fe0040, /* XXX copied from RTL8139A, verify */ + }, + + { "RTL-8139C", + 0x74000000, + 0xf0fc0040, /* XXX copied from RTL8139B, verify */ + }, + }; @@ -574,12 +619,8 @@ /* enable device (incl. PCI PM wakeup), and bus-mastering */ rc = pci_enable_device (pdev); - if (rc) { - printk (KERN_ERR PFX "cannot enable PCI device (bus %d, " - "devfn %d), aborting\n", - pdev->bus->number, pdev->devfn); + if (rc) goto err_out_free_mmio; - } pci_set_master (pdev); @@ -631,15 +672,20 @@ } /* identify chip attached to board */ - tmp = RTL_R32 (TxConfig); - if (((tmp >> 28) & 7) == 7) { - if (pio_len == RTL8139B_IO_SIZE) - tp->chipset = CH_8139B; - else - tp->chipset = CH_8139A; - } else { - tp->chipset = CH_8139; - } + tmp = RTL_R32 (TxConfig) & TxVersionMask; + for (i = arraysize (rtl_chip_info) - 1; i >= 0; i--) + if (tmp == rtl_chip_info[i].version) { + tp->chipset = i; + goto match; + } + + /* if unknown chip, assume array element #0, original RTL-8139 in this case */ + printk (KERN_DEBUG PFX "PCI device %s: unknown chip version, assuming RTL-8139\n", + pdev->slot_name); + printk (KERN_DEBUG PFX "PCI device %s: TxConfig = 0x%x\n", pdev->slot_name, RTL_R32 (TxConfig)); + tp->chipset = 0; + +match: DPRINTK ("chipset id (%d/%d/%d) == %d, '%s'\n", CH_8139, CH_8139A, @@ -738,7 +784,7 @@ tp->phys[0] = 32; - printk (KERN_INFO "%s: '%s' board found at 0x%lx, IRQ %d\n", + printk (KERN_INFO "%s: %s board found at 0x%lx, IRQ %d\n", dev->name, board_info[ent->driver_data].name, dev->base_addr, dev->irq); @@ -1122,6 +1168,7 @@ /* Check this value: the documentation for IFG contradicts ifself. */ RTL_W32 (TxConfig, (TX_DMA_BURST << 8)); +#if 0 /* if link status not ok... */ if ((RTL_R16 (BasicModeStatus) & (1<<2)) == 0) { printk (KERN_INFO "%s: no link, starting NWay\n", dev->name); @@ -1144,10 +1191,13 @@ /* XXX writing Config1 here is flat out wrong */ /* RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20); */ } +#endif - tmp = RTL_R8 (Config1) & Config1Clear; - tmp |= (tp->chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */ - RTL_W8_F (Config1, tmp); + if (tp->chipset > CH_8139) { + tmp = RTL_R8 (Config1) & Config1Clear; + tmp |= (tp->chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */ + RTL_W8_F (Config1, tmp); + } if (tp->chipset == CH_8139B) { tmp = RTL_R8 (Config4) & ~(1<<2); @@ -1596,13 +1646,19 @@ /* A.C.: Reset the multicast list. */ rtl8139_set_rx_mode (dev); + /* XXX potentially temporary hack to + * restart hung receiver */ while (--tmp_work > 0) { - tmp8 = RTL_R8 (ChipCmd) & ChipCmdClear; + tmp8 = RTL_R8 (ChipCmd); if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb)) break; - RTL_W8_F (ChipCmd, tmp8 | CmdRxEnb | CmdTxEnb); + RTL_W8_F (ChipCmd, (tmp8 & ChipCmdClear) | CmdRxEnb | CmdTxEnb); } + /* G.S.: Re-enable receiver */ + /* XXX temporary hack to work around receiver hang */ + rtl8139_set_rx_mode (dev); + if (tmp_work <= 0) printk (KERN_WARNING PFX "tx/rx enable wait too long\n"); } else { @@ -1973,7 +2029,6 @@ u32 mc_filter[2]; /* Multicast hash filter */ int i, rx_mode; u32 tmp; - unsigned long flags=0; DPRINTK ("ENTER\n"); @@ -2006,7 +2061,7 @@ /* if called from irq handler, lock already acquired */ if (!in_irq ()) - spin_lock_irqsave (&tp->lock, flags); + spin_lock_irq (&tp->lock); /* We can safely update without stopping the chip. */ tmp = rtl8139_rx_config | rx_mode | @@ -2016,7 +2071,7 @@ RTL_W32_F (MAR0 + 4, mc_filter[1]); if (!in_irq ()) - spin_unlock_irqrestore (&tp->lock, flags); + spin_unlock_irq (&tp->lock); DPRINTK ("EXIT\n"); } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.3.99-pre8/linux/drivers/net/Config.in Fri May 12 14:18:55 2000 +++ linux/drivers/net/Config.in Sat May 20 12:05:30 2000 @@ -51,6 +51,9 @@ if [ "$CONFIG_SGI_IP27" = "y" ]; then bool ' SGI IOC3 Ethernet' CONFIG_SGI_IOC3_ETH fi + if [ "$CONFIG_SUPERH" = "y" -a "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then + tristate ' National DP83902AV support' CONFIG_STNIC + fi bool ' 3COM cards' CONFIG_NET_VENDOR_3COM if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then tristate ' 3c501 "EtherLink" support' CONFIG_EL1 @@ -218,7 +221,7 @@ dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP - dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP + dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP fi diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.3.99-pre8/linux/drivers/net/Makefile Fri May 12 14:18:55 2000 +++ linux/drivers/net/Makefile Sat May 20 12:05:30 2000 @@ -146,6 +146,8 @@ obj-$(CONFIG_YELLOWFIN) += yellowfin.o obj-$(CONFIG_ACENIC) += acenic.o +obj-$(CONFIG_STNIC) += stnic.o 8390.o + ifeq ($(CONFIG_SK98LIN),y) SUB_DIRS += sk98lin obj-y += sk98lin/sk98lin.o diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v2.3.99-pre8/linux/drivers/net/Space.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/net/Space.c Mon May 15 12:00:34 2000 @@ -95,10 +95,6 @@ extern int pamsnet_probe(struct net_device *); extern int cs89x0_probe(struct net_device *dev); extern int ethertap_probe(struct net_device *dev); -extern int ether1_probe (struct net_device *dev); -extern int ether3_probe (struct net_device *dev); -extern int etherh_probe (struct net_device *dev); -extern int am79c961_probe(struct net_device *dev); extern int hplance_probe(struct net_device *dev); extern int bagetlance_probe(struct net_device *); extern int dec_lance_probe(struct net_device *); @@ -401,22 +397,6 @@ {NULL, 0}, }; -struct devprobe arm_probes[] __initdata = { -#ifdef CONFIG_ARM_ETHERH - {etherh_probe , 0}, -#endif -#ifdef CONFIG_ARM_ETHER3 - {ether3_probe , 0}, -#endif -#ifdef CONFIG_ARM_ETHER1 - {ether1_probe , 0}, -#endif -#ifdef CONFIG_ARM_AM79C961A - {am79c961_probe, 0}, -#endif - {NULL, 0}, -}; - /* * Unified ethernet device probe, segmented per architecture and * per bus interface. This drives the legacy devices only for now. @@ -437,8 +417,6 @@ * The arch specific probes are 1st so that any on-board ethernet * will be probed before other ISA/EISA/MCA/PCI bus cards. */ - if (probe_list(dev, arm_probes) == 0) - return 0; if (probe_list(dev, m68k_probes) == 0) return 0; if (probe_list(dev, mips_probes) == 0) diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/acenic.c linux/drivers/net/acenic.c --- v2.3.99-pre8/linux/drivers/net/acenic.c Fri May 12 14:18:55 2000 +++ linux/drivers/net/acenic.c Mon May 15 12:10:26 2000 @@ -2966,6 +2966,6 @@ /* * Local variables: - * compile-command: "gcc -D__SMP__ -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c" + * compile-command: "gcc -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c" * End: */ diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/am79c961a.c linux/drivers/net/am79c961a.c --- v2.3.99-pre8/linux/drivers/net/am79c961a.c Wed Apr 26 16:34:07 2000 +++ linux/drivers/net/am79c961a.c Mon May 15 12:00:34 2000 @@ -3,7 +3,10 @@ * * Derived from various things including skeleton.c * - * R.M.King 1995. + * Russell King 1995-2000. + * + * This is a special driver for the am79c961A Lance chip used in the + * Intel (formally Digital Equipment Corp) EBSA110 platform. */ #include #include @@ -21,9 +24,11 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -33,26 +38,13 @@ #include "am79c961a.h" -static int am79c961_probe1 (struct net_device *dev); -static int am79c961_open (struct net_device *dev); -static int am79c961_sendpacket (struct sk_buff *skb, struct net_device *dev); static void am79c961_interrupt (int irq, void *dev_id, struct pt_regs *regs); static void am79c961_rx (struct net_device *dev, struct dev_priv *priv); static void am79c961_tx (struct net_device *dev, struct dev_priv *priv); -static int am79c961_close (struct net_device *dev); -static struct enet_statistics *am79c961_getstats (struct net_device *dev); -static void am79c961_setmulticastlist (struct net_device *dev); -static void am79c961_timeout(struct net_device *dev); static unsigned int net_debug = NET_DEBUG; -static void -am79c961_setmulticastlist (struct net_device *dev); - -static char *version = "am79c961 ethernet driver (c) 1995 R.M.King v0.01\n"; - -#define FUNC_PROLOGUE \ - struct dev_priv *priv = (struct dev_priv *)dev->priv +static char *version = "am79c961 ethernet driver (c) 1995 R.M.King v0.02\n"; /* --------------------------------------------------------------------------- */ @@ -270,109 +262,6 @@ write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT); } -static int -am79c961_init(struct net_device *dev) -{ - unsigned long flags; - - am79c961_ramtest(dev, 0x66); - am79c961_ramtest(dev, 0x99); - - save_flags_cli (flags); - - write_ireg (dev->base_addr, 2, 0x4000); /* autoselect media */ - write_rreg (dev->base_addr, CSR0, CSR0_STOP); - write_rreg (dev->base_addr, CSR3, CSR3_MASKALL); - - restore_flags (flags); - - return 0; -} - -/* - * This is the real probe routine. - */ -static int -am79c961_probe1(struct net_device *dev) -{ - static unsigned version_printed = 0; - struct dev_priv *priv; - int i; - - if (!dev->priv) { - dev->priv = kmalloc (sizeof (struct dev_priv), GFP_KERNEL); - if (!dev->priv) - return -ENOMEM; - } - - priv = (struct dev_priv *) dev->priv; - memset (priv, 0, sizeof(struct dev_priv)); - - /* - * The PNP initialisation should have been done by the ether bootp loader. - */ - inb((dev->base_addr + NET_RESET) >> 1); /* reset the device */ - - udelay (5); - - if (inb (dev->base_addr >> 1) != 0x08 || - inb ((dev->base_addr >> 1) + 1) != 00 || - inb ((dev->base_addr >> 1) + 2) != 0x2b) { - kfree (dev->priv); - dev->priv = NULL; - return -ENODEV; - } - - /* - * Ok, we've found a valid hw ID - */ - - if (net_debug && version_printed++ == 0) - printk (KERN_INFO "%s", version); - - printk(KERN_INFO "%s: am79c961 found [%04lx, %d] ", dev->name, dev->base_addr, dev->irq); - request_region (dev->base_addr, 0x18, "am79c961"); - - /* Retrive and print the ethernet address. */ - for (i = 0; i < 6; i++) { - dev->dev_addr[i] = inb ((dev->base_addr >> 1) + i) & 0xff; - printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]); - } - - if (am79c961_init(dev)) { - kfree (dev->priv); - dev->priv = NULL; - return -ENODEV; - } - - dev->open = am79c961_open; - dev->stop = am79c961_close; - dev->hard_start_xmit = am79c961_sendpacket; - dev->get_stats = am79c961_getstats; - dev->set_multicast_list = am79c961_setmulticastlist; - dev->tx_timeout = am79c961_timeout; - - /* Fill in the fields of the device structure with ethernet values. */ - ether_setup(dev); - - return 0; -} - -int -am79c961_probe(struct net_device *dev) -{ - static int initialised = 0; - - if (initialised) - return -ENODEV; - initialised = 1; - - dev->base_addr = 0x220; - dev->irq = 3; - - return am79c961_probe1(dev); -} - /* * Open/initialize the board. This is called (in the current kernel) * sometime after booting when the 'ifconfig' program is run. @@ -408,9 +297,17 @@ static int am79c961_close(struct net_device *dev) { + unsigned long flags; + netif_stop_queue(dev); - am79c961_init(dev); + save_flags_cli (flags); + + write_ireg (dev->base_addr, 2, 0x4000); /* autoselect media */ + write_rreg (dev->base_addr, CSR0, CSR0_STOP); + write_rreg (dev->base_addr, CSR3, CSR3_MASKALL); + + restore_flags (flags); free_irq (dev->irq, dev); @@ -709,3 +606,103 @@ netif_wake_queue(dev); } + +static int +am79c961_hw_init(struct net_device *dev) +{ + unsigned long flags; + + am79c961_ramtest(dev, 0x66); + am79c961_ramtest(dev, 0x99); + + save_flags_cli (flags); + + write_ireg (dev->base_addr, 2, 0x4000); /* autoselect media */ + write_rreg (dev->base_addr, CSR0, CSR0_STOP); + write_rreg (dev->base_addr, CSR3, CSR3_MASKALL); + + restore_flags (flags); + + return 0; +} + +static void __init am79c961_banner(void) +{ + static unsigned version_printed = 0; + + if (net_debug && version_printed++ == 0) + printk(KERN_INFO "%s", version); +} + +static int __init am79c961_init(void) +{ + struct net_device *dev; + struct dev_priv *priv; + int i, ret; + + dev = init_etherdev(NULL, sizeof(struct dev_priv)); + ret = -ENOMEM; + if (!dev) + goto out; + + priv = (struct dev_priv *) dev->priv; + + /* + * Fixed address and IRQ lines here. + * The PNP initialisation should have been + * done by the ether bootp loader. + */ + dev->base_addr = 0x220; + dev->irq = IRQ_EBSA110_ETHERNET; + + /* + * Reset the device. + */ + inb((dev->base_addr + NET_RESET) >> 1); + udelay(5); + + /* + * Check the manufacturer part of the + * ether address. + */ + ret = -ENODEV; + if (inb(dev->base_addr >> 1) != 0x08 || + inb((dev->base_addr >> 1) + 1) != 00 || + inb((dev->base_addr >> 1) + 2) != 0x2b) + goto nodev; + + if (!request_region(dev->base_addr, 0x18, dev->name)) + goto nodev; + + am79c961_banner(); + printk(KERN_INFO "%s: am79c961 found at %08lx, IRQ%d, ether address ", + dev->name, dev->base_addr, dev->irq); + + /* Retrive and print the ethernet address. */ + for (i = 0; i < 6; i++) { + dev->dev_addr[i] = inb((dev->base_addr >> 1) + i) & 0xff; + printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]); + } + + if (am79c961_hw_init(dev)) + goto release; + + dev->open = am79c961_open; + dev->stop = am79c961_close; + dev->hard_start_xmit = am79c961_sendpacket; + dev->get_stats = am79c961_getstats; + dev->set_multicast_list = am79c961_setmulticastlist; + dev->tx_timeout = am79c961_timeout; + + return 0; + +release: + release_region(dev->base_addr, 0x18); +nodev: + unregister_netdev(dev); + kfree(dev); +out: + return ret; +} + +module_init(am79c961_init); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/arcnet/arc-rimi.c linux/drivers/net/arcnet/arc-rimi.c --- v2.3.99-pre8/linux/drivers/net/arcnet/arc-rimi.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/arcnet/arc-rimi.c Sat May 13 07:50:25 2000 @@ -345,9 +345,8 @@ s = get_options(s, 8, ints); if (!ints[0]) return 1; - dev = alloc_bootmem(sizeof(struct net_device) + 10); - memset(dev, 0, sizeof(struct net_device) + 10); - dev->name = (char *) (dev + 1); + dev = alloc_bootmem(sizeof(struct net_device)); + memset(dev, 0, sizeof(struct net_device)); dev->init = arcrimi_probe; switch (ints[0]) { diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/arcnet/com20020-isa.c linux/drivers/net/arcnet/com20020-isa.c --- v2.3.99-pre8/linux/drivers/net/arcnet/com20020-isa.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/arcnet/com20020-isa.c Sat May 13 07:50:25 2000 @@ -194,10 +194,9 @@ s = get_options(s, 8, ints); if (!ints[0]) return 1; - dev = alloc_bootmem(sizeof(struct net_device) + sizeof(struct arcnet_local) + 10); - memset(dev, 0, sizeof(struct net_device) + sizeof(struct arcnet_local) + 10); + dev = alloc_bootmem(sizeof(struct net_device) + sizeof(struct arcnet_local)); + memset(dev, 0, sizeof(struct net_device) + sizeof(struct arcnet_local)); lp = dev->priv = (struct arcnet_local *) (dev + 1); - dev->name = (char *) (lp + 1); dev->init = com20020isa_probe; switch (ints[0]) { diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/arcnet/com20020-pci.c linux/drivers/net/arcnet/com20020-pci.c --- v2.3.99-pre8/linux/drivers/net/arcnet/com20020-pci.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/arcnet/com20020-pci.c Sat May 13 08:19:21 2000 @@ -139,7 +139,9 @@ {0,} }; -static struct pci_driver com20020pci_driver __devinitdata = { +MODULE_DEVICE_TABLE(pci, com20020pci_id_table); + +static struct pci_driver com20020pci_driver = { name: "com20020", id_table: com20020pci_id_table, probe: com20020pci_probe, diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/arcnet/com90io.c linux/drivers/net/arcnet/com90io.c --- v2.3.99-pre8/linux/drivers/net/arcnet/com90io.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/arcnet/com90io.c Sat May 13 07:50:25 2000 @@ -428,9 +428,8 @@ s = get_options(s, 4, ints); if (!ints[0]) return 0; - dev = alloc_bootmem(sizeof(struct net_device) + 10); - memset(dev, 0, sizeof(struct net_device) + 10); - dev->name = (char *) (dev + 1); + dev = alloc_bootmem(sizeof(struct net_device)); + memset(dev, 0, sizeof(struct net_device)); dev->init = com90io_probe; switch (ints[0]) { diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/arcnet/com90xx.c linux/drivers/net/arcnet/com90xx.c --- v2.3.99-pre8/linux/drivers/net/arcnet/com90xx.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/arcnet/com90xx.c Sat May 13 07:50:25 2000 @@ -677,9 +677,8 @@ printk("com90xx: Disabled.\n"); return 1; } - dev = alloc_bootmem(sizeof(struct net_device) + 10); - memset(dev, 0, sizeof(struct net_device) + 10); - dev->name = (char *) (dev + 1); + dev = alloc_bootmem(sizeof(struct net_device)); + memset(dev, 0, sizeof(struct net_device)); dev->init = com90xx_probe; switch (ints[0]) { diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/bagetlance.c linux/drivers/net/bagetlance.c --- v2.3.99-pre8/linux/drivers/net/bagetlance.c Sat Feb 26 22:31:46 2000 +++ linux/drivers/net/bagetlance.c Sat May 13 08:29:40 2000 @@ -1,4 +1,4 @@ -/* $Id: bagetlance.c,v 1.2 1999/10/09 00:01:21 ralf Exp $ +/* $Id$ * vmelance.c: Ethernet driver for VME Lance cards on Baget/MIPS * This code stealed and adopted from linux/drivers/net/atarilance.c * See that for author info diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/declance.c linux/drivers/net/declance.c --- v2.3.99-pre8/linux/drivers/net/declance.c Sat Feb 26 22:31:46 2000 +++ linux/drivers/net/declance.c Sat May 13 08:29:40 2000 @@ -256,6 +256,8 @@ volatile struct lance_init_block *init_block; volatile unsigned long *dma_ptr_reg; + spinlock_t lock; + int rx_new, tx_new; int rx_old, tx_old; @@ -265,6 +267,7 @@ struct net_device *dev; /* Backpointer */ struct lance_private *next_module; + struct timer_list multicast_timer; /* Pointers to the ring buffers as seen from the CPU */ char *rx_buf_ptr_cpu[RX_RING_SIZE]; @@ -443,7 +446,6 @@ } /* Setup the Lance Rx and Tx rings */ -/* Sets dev->tbusy */ static void lance_init_ring(struct net_device *dev) { struct lance_private *lp = (struct lance_private *) dev->priv; @@ -454,12 +456,10 @@ ib = (struct lance_init_block *) (dev->mem_start); /* Lock out other processes while setting up hardware */ - dev->tbusy = 1; + netif_stop_queue(dev); lp->rx_new = lp->tx_new = 0; lp->rx_old = lp->tx_old = 0; - ib->mode = 0; - /* Copy the ethernet address to the lance init block. * XXX bit 0 of the physical address registers has to be zero */ @@ -485,11 +485,6 @@ if (ZERO) printk("TX ptr: %8.8x(%8.8x)\n", leptr, libdesc_offset(btx_ring, 0)); - /* Clear the multicast filter */ - ib->filter[0] = 0; - ib->filter[2] = 0; - ib->filter[4] = 0; - ib->filter[6] = 0; if (ZERO) printk("TX rings:\n"); @@ -630,7 +625,7 @@ return 0; } -static int lance_tx(struct net_device *dev) +static void lance_tx(struct net_device *dev) { struct lance_private *lp = (struct lance_private *) dev->priv; volatile struct lance_init_block *ib; @@ -641,6 +636,8 @@ ib = (struct lance_init_block *) (dev->mem_start); j = lp->tx_old; + spin_lock(&lp->lock); + for (i = j; i != lp->tx_new; i = j) { td = &ib->btx_ring[i]; /* If we hit a packet not owned by us, stop */ @@ -665,7 +662,7 @@ lance_init_ring(dev); load_csrs(lp); init_restart_lance(lp); - return 0; + goto out; } /* Buffer errors and underflows turn off the * transmitter, restart the adapter. @@ -681,7 +678,7 @@ lance_init_ring(dev); load_csrs(lp); init_restart_lance(lp); - return 0; + goto out; } } else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) { /* @@ -702,7 +699,12 @@ j = (j + 1) & TX_RING_MOD_MASK; } lp->tx_old = j; - return 0; +out: + if (netif_queue_stopped(dev) && + TX_BUFFS_AVAIL > 0) + netif_wake_queue(dev); + + spin_unlock(&lp->lock); } static void lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs) @@ -712,11 +714,6 @@ volatile struct lance_regs *ll = lp->ll; int csr0; - if (dev->interrupt) - printk("%s: again\n", dev->name); - - dev->interrupt = 1; - writereg(&ll->rap, LE_CSR0); csr0 = ll->rdp; @@ -734,10 +731,6 @@ if (csr0 & LE_C0_TINT) lance_tx(dev); - if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { - dev->tbusy = 0; - mark_bh(NET_BH); - } if (csr0 & LE_C0_BABL) lp->stats.tx_errors++; @@ -763,17 +756,17 @@ lance_init_ring(dev); load_csrs(lp); init_restart_lance(lp); - dev->tbusy = 0; + netif_wake_queue(dev); } writereg(&ll->rdp, LE_C0_INEA); writereg(&ll->rdp, LE_C0_INEA); - dev->interrupt = 0; } struct net_device *last_dev = 0; static int lance_open(struct net_device *dev) { + volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start); struct lance_private *lp = (struct lance_private *) dev->priv; volatile struct lance_regs *ll = lp->ll; int status = 0; @@ -789,12 +782,20 @@ writereg(&ll->rap, LE_CSR0); writereg(&ll->rdp, LE_C0_STOP); + /* Set mode and clear multicast filter only at device open, + * so that lance_init_ring() called at any error will not + * forget multicast filters. + * + * BTW it is common bug in all lance drivers! --ANK + */ + ib->mode = 0; + ib->filter [0] = 0; + ib->filter [2] = 0; + lance_init_ring(dev); load_csrs(lp); - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; + netif_start_queue(dev); status = init_restart_lance(lp); @@ -811,8 +812,8 @@ struct lance_private *lp = (struct lance_private *) dev->priv; volatile struct lance_regs *ll = lp->ll; - dev->start = 0; - dev->tbusy = 1; + netif_stop_queue(dev); + del_timer_sync(&lp->multicast_timer); /* Stop the card */ writereg(&ll->rap, LE_CSR0); @@ -838,51 +839,30 @@ lance_init_ring(dev); load_csrs(lp); dev->trans_start = jiffies; - dev->interrupt = 0; - dev->start = 1; - dev->tbusy = 0; status = init_restart_lance(lp); -#ifdef DEBUG_DRIVER - printk("Lance restart=%d\n", status); -#endif return status; } -static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) +static void lance_tx_timeout(struct net_device *dev) { struct lance_private *lp = (struct lance_private *) dev->priv; volatile struct lance_regs *ll = lp->ll; - volatile struct lance_init_block *ib; - unsigned long flags; - int entry, skblen, len; - int status = 0; - static int outs; - ib = (struct lance_init_block *) (dev->mem_start); - - /* Transmitter timeout, serious problems */ - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 100) { - status = -1; - } else { - printk("%s: transmit timed out, status %04x, reset\n", + printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n", dev->name, ll->rdp); lance_reset(dev); - } - return status; - } - /* Block a timer-based transmit from overlapping. */ - if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) { - printk("Transmitter access conflict.\n"); - return -1; - } + netif_wake_queue(dev); +} + +static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct lance_private *lp = (struct lance_private *) dev->priv; + volatile struct lance_regs *ll = lp->ll; + volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start); + int entry, skblen, len; + skblen = skb->len; - save_and_cli(flags); - if (!TX_BUFFS_AVAIL) { - restore_flags(flags); - return -1; - } + len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen; lp->stats.tx_bytes += len; @@ -904,17 +884,18 @@ ib->btx_ring[entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN); lp->tx_new = (lp->tx_new + 1) & TX_RING_MOD_MASK; - outs++; + if (TX_BUFFS_AVAIL <= 0) + netif_stop_queue(dev); + /* Kick the lance: transmit now */ writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD); + + spin_unlock_irq(&lp->lock); + dev->trans_start = jiffies; dev_kfree_skb(skb); - if (TX_BUFFS_AVAIL) - dev->tbusy = 0; - - restore_flags(flags); - return status; + return 0; } static struct net_device_stats *lance_get_stats(struct net_device *dev) @@ -983,11 +964,16 @@ ib = (struct lance_init_block *) (dev->mem_start); - while (dev->tbusy) - schedule(); - set_bit(0, (void *) &dev->tbusy); - while (lp->tx_old != lp->tx_new) - schedule(); + if (!netif_running(dev)) + return; + + if (lp->tx_old != lp->tx_new) { + mod_timer(&lp->multicast_timer, jiffies + 4); + netif_wake_queue(dev); + return; + } + + netif_stop_queue(dev); writereg(&ll->rap, LE_CSR0); writereg(&ll->rdp, LE_C0_STOP); @@ -1002,7 +988,14 @@ } load_csrs(lp); init_restart_lance(lp); - dev->tbusy = 0; + netif_wake_queue(dev); +} + +static void lance_set_multicast_retry(unsigned long _opaque) +{ + struct net_device *dev = (struct net_device *) _opaque; + + lance_set_multicast(dev); } static int __init dec_lance_init(struct net_device *dev, const int type) @@ -1167,14 +1160,14 @@ printk(" irq = %d\n", dev->irq); - /* Fill the dev fields */ - - dev->open = lance_open; - dev->stop = lance_close; - dev->hard_start_xmit = lance_start_xmit; - dev->get_stats = lance_get_stats; - dev->set_multicast_list = lance_set_multicast; - dev->dma = 0; + lp->dev = dev; + dev->open = &lance_open; + dev->stop = &lance_close; + dev->hard_start_xmit = &lance_start_xmit; + dev->tx_timeout = &lance_tx_timeout; + dev->watchdog_timeo = 5*HZ; + dev->get_stats = &lance_get_stats; + dev->set_multicast_list = &lance_set_multicast; /* lp->ll is the location of the registers for lance card */ lp->ll = ll; @@ -1185,25 +1178,39 @@ * specification. */ lp->busmaster_regval = 0; - lp->dev = dev; + + dev->dma = 0; ether_setup(dev); -/* - #ifdef MODULE + + /* We cannot sleep if the chip is busy during a + * multicast list update event, because such events + * can occur from interrupts (ex. IPv6). So we + * use a timer to try again later when necessary. -DaveM + */ + init_timer(&lp->multicast_timer); + lp->multicast_timer.data = (unsigned long) dev; + lp->multicast_timer.function = &lance_set_multicast_retry; + +#ifdef MODULE dev->ifindex = dev_new_index(); lp->next_module = root_lance_dev; root_lance_dev = lp; - #endif - */ +#endif return 0; } /* Find all the lance cards on the system and initialize them */ -int __init dec_lance_probe(struct net_device *dev) +static int __init dec_lance_probe(void) { + struct net_device *dev = NULL; static int called = 0; +#ifdef MODULE + root_lance_dev = NULL; +#endif + #ifdef CONFIG_TC int slot = -1; @@ -1238,19 +1245,9 @@ return dec_lance_init(dev, type); } -/* - #ifdef MODULE - - int - init_module(void) - { - root_lance_dev = NULL; - return dec_lance_probe(NULL); - } - - void - cleanup_module(void) - { +static void __exit dec_lance_cleanup(void) +{ +#ifdef MODULE struct lance_private *lp; while (root_lance_dev) { @@ -1260,6 +1257,8 @@ kfree(root_lance_dev->dev); root_lance_dev = lp; } - } +#endif /* MODULE */ +} - #endif -* MODULE */ +module_init(dec_lance_probe); +module_exit(dec_lance_cleanup); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c --- v2.3.99-pre8/linux/drivers/net/eepro100.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/eepro100.c Sat May 13 08:19:21 2000 @@ -2206,7 +2206,7 @@ PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER, PCI_ANY_ID, PCI_ANY_ID, }, - { 0,}, + { 0,} }; MODULE_DEVICE_TABLE(pci, eepro100_pci_tbl); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/epic100.c linux/drivers/net/epic100.c --- v2.3.99-pre8/linux/drivers/net/epic100.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/epic100.c Sat May 13 08:19:21 2000 @@ -189,7 +189,7 @@ { 0x10B8, 0x0005, 0x1092, 0x0AB4, 0, 0, SMSC_83C170_0 }, { 0x10B8, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMSC_83C170 }, { 0x10B8, 0x0006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMSC_83C175 }, - { 0,}, + { 0,} }; MODULE_DEVICE_TABLE (pci, epic_pci_tbl); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/hp100.c linux/drivers/net/hp100.c --- v2.3.99-pre8/linux/drivers/net/hp100.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/hp100.c Sun May 21 20:18:08 2000 @@ -3123,11 +3123,11 @@ MODULE_PARM(hp100_port, "1-5i"); #endif -#ifndef LINUX_2_1 -static char devname[5][IFNAMSIZ] = { "", "", "", "", "" }; -static char *hp100_name[5] = { devname[0], devname[1], - devname[2], devname[3], - devname[4] }; +/* Allocate 5 string of length IFNAMSIZ, one string for each device */ +char hp100_name[5][IFNAMSIZ] = { "", "", "", "", "" }; +#ifdef LINUX_2_1 +/* Allow insmod to write those 5 strings individually */ +MODULE_PARM(hp100_name, "1-5c" __MODULE_STRING(IFNAMSIZ)); #endif /* List of devices */ @@ -3159,9 +3159,11 @@ /* Create device and set basics args */ hp100_devlist[i] = kmalloc(sizeof(struct net_device), GFP_KERNEL); memset(hp100_devlist[i], 0x00, sizeof(struct net_device)); -#ifndef LINUX_2_1 +#if LINUX_VERSION_CODE >= 0x020362 /* 2.3.99-pre7 */ + memcpy(hp100_devlist[i]->name, hp100_name[i], IFNAMSIZ); /* Copy name */ +#else hp100_devlist[i]->name = hp100_name[i]; -#endif +#endif /* LINUX_VERSION_CODE >= 0x020362 */ hp100_devlist[i]->base_addr = hp100_port[i]; hp100_devlist[i]->init = &hp100_probe; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/ioc3-eth.c linux/drivers/net/ioc3-eth.c --- v2.3.99-pre8/linux/drivers/net/ioc3-eth.c Thu Mar 2 14:36:22 2000 +++ linux/drivers/net/ioc3-eth.c Sat May 13 08:29:40 2000 @@ -97,6 +97,7 @@ int rx_pi; /* RX producer index */ int tx_ci; /* TX consumer index */ int tx_pi; /* TX producer index */ + spinlock_t ioc3_lock; }; /* We use this to acquire receive skb's that we can DMA directly into. */ @@ -390,6 +391,7 @@ struct sk_buff *skb; u32 etcir; + spin_lock(&ip->ioc3_lock); etcir = ioc3->etcir; tx_entry = (etcir >> 7) & 127; o_entry = ip->tx_ci; @@ -401,7 +403,7 @@ skb = ip->tx_skbs[o_entry]; ip->stats.tx_packets++; ip->stats.tx_bytes += skb->len; - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); ip->tx_skbs[o_entry] = NULL; o_entry = (o_entry + 1) & 127; /* Next */ @@ -410,6 +412,7 @@ tx_entry = (etcir >> 7) & 127; } ip->tx_ci = o_entry; + spin_unlock(&ip->ioc3_lock); } /* @@ -602,20 +605,30 @@ static void ioc3_probe1(struct net_device *dev, struct ioc3 *ioc3) { - struct ioc3_private *p; + struct ioc3_private *ip; dev = init_etherdev(dev, 0); - p = (struct ioc3_private *) kmalloc(sizeof(*p), GFP_KERNEL); - memset(p, 0, sizeof(*p)); - dev->priv = p; + + /* + * This probably needs to be register_netdevice, or call + * init_etherdev so that it calls register_netdevice. Quick + * hack for now. + */ + netif_device_attach(dev); + + ip = (struct ioc3_private *) kmalloc(sizeof(*ip), GFP_KERNEL); + memset(ip, 0, sizeof(*ip)); + dev->priv = ip; dev->irq = IOC3_ETH_INT; - p->regs = ioc3; + ip->regs = ioc3; - ioc3_eth_init(dev, p, ioc3); - ioc3_ssram_disc(p); + ioc3_eth_init(dev, ip, ioc3); + ioc3_ssram_disc(ip); ioc3_get_eaddr(dev, ioc3); - ioc3_init_rings(dev, p, ioc3); + ioc3_init_rings(dev, ip, ioc3); + + spin_lock_init(&ip->ioc3_lock); /* Misc registers */ ioc3->erbar = 0; @@ -702,6 +715,7 @@ return 1; } + spin_lock_irq(&ip->ioc3_lock); data = (unsigned long) skb->data; len = skb->len; @@ -718,7 +732,7 @@ } desc->cmd = len | ETXD_INTWHENDONE | ETXD_D0V; desc->bufcnt = len; - } if ((data ^ (data + len)) & 0x4000) { + } else if ((data ^ (data + len)) & 0x4000) { unsigned long b2, s1, s2; b2 = (data | 0x3fffUL) + 1UL; @@ -747,6 +761,7 @@ if (TX_BUFFS_AVAIL(ip)) netif_wake_queue(dev); + spin_unlock_irq(&ip->ioc3_lock); return 0; } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/ncr885e.c linux/drivers/net/ncr885e.c --- v2.3.99-pre8/linux/drivers/net/ncr885e.c Tue Mar 7 14:32:26 2000 +++ linux/drivers/net/ncr885e.c Sat May 20 12:07:56 2000 @@ -424,7 +424,7 @@ /* look for any channel status (?) */ if ( xfer ) { - dev_kfree_skb( sp->tx_skbufs[i] ); + dev_kfree_skb_irq( sp->tx_skbufs[i] ); if ( txbits & TX_STATUS_TXOK ) { sp->stats.tx_packets++; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c --- v2.3.99-pre8/linux/drivers/net/ne2k-pci.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/ne2k-pci.c Sat May 13 08:19:21 2000 @@ -115,7 +115,7 @@ { 0x1050, 0x5a5a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_W89C940F }, { 0x12c3, 0x0058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80232 }, { 0x12c3, 0x5598, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80229 }, - { 0, }, + { 0, } }; MODULE_DEVICE_TABLE(pci, ne2k_pci_tbl); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c --- v2.3.99-pre8/linux/drivers/net/pcnet32.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/pcnet32.c Sat May 13 08:19:21 2000 @@ -334,8 +334,10 @@ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_PCNETHOME, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0x1014, 0x2000, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0 }, + { 0, } }; + +MODULE_DEVICE_TABLE (pci, pcnet32_pci_tbl); static u16 pcnet32_wio_read_csr (unsigned long addr, int index) { diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/ppp_synctty.c linux/drivers/net/ppp_synctty.c --- v2.3.99-pre8/linux/drivers/net/ppp_synctty.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/net/ppp_synctty.c Sat May 20 11:34:54 2000 @@ -269,12 +269,22 @@ err = -EFAULT; switch (cmd) { - case PPPIOCGUNIT: + case PPPIOCGCHAN: err = -ENXIO; if (ap == 0) break; err = -EFAULT; if (put_user(ppp_channel_index(&ap->chan), (int *) arg)) + break; + err = 0; + break; + + case PPPIOCGUNIT: + err = -ENXIO; + if (ap == 0) + break; + err = -EFAULT; + if (put_user(ppp_unit_number(&ap->chan), (int *) arg)) break; err = 0; break; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/pppoe.c linux/drivers/net/pppoe.c --- v2.3.99-pre8/linux/drivers/net/pppoe.c Fri May 12 14:18:55 2000 +++ linux/drivers/net/pppoe.c Mon May 22 09:50:55 2000 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -46,10 +47,12 @@ static int __attribute__((unused)) pppoe_debug = 7; -#define PPPOE_HASH_SIZE 16 +#define PPPOE_HASH_BITS 4 +#define PPPOE_HASH_SIZE (1<> ( j * PPPOE_HASH_BITS ); + } + } - i = (int) (hash.c[0] & (PPPOE_HASH_SIZE - 1)); + for (i = 0; i < (sizeof(unsigned long)*8) / PPPOE_HASH_BITS ; ++i) + hash ^= sid >> (i*PPPOE_HASH_BITS); - return i; + return hash & ( PPPOE_HASH_SIZE - 1 ); } static struct pppox_opt *item_hash_table[PPPOE_HASH_SIZE] = { 0, }; @@ -105,7 +103,7 @@ /********************************************************************** * * Set/get/delete/rehash items (internal versions) - * + * **********************************************************************/ static struct pppox_opt *__get_item(unsigned long sid, unsigned char *addr) { @@ -162,7 +160,7 @@ return ret; } -static struct pppox_opt *__find_on_dev(struct net_device *dev, +static struct pppox_opt *__find_on_dev(struct net_device *dev, struct pppox_opt *start) { struct pppox_opt *po; @@ -195,9 +193,9 @@ /********************************************************************** * * Set/get/delete/rehash items - * + * **********************************************************************/ -static inline struct pppox_opt *get_item(unsigned long sid, +static inline struct pppox_opt *get_item(unsigned long sid, unsigned char *addr) { struct pppox_opt *po; @@ -239,7 +237,7 @@ return ret; } -static struct pppox_opt *find_on_dev(struct net_device *dev, +static struct pppox_opt *find_on_dev(struct net_device *dev, struct pppox_opt *start) { struct pppox_opt *po; @@ -255,7 +253,7 @@ * Certain device events require that sockets be unconnected * **************************************************************************/ -static int pppoe_device_event(struct notifier_block *this, +static int pppoe_device_event(struct notifier_block *this, unsigned long event, void *ptr) { int error = NOTIFY_DONE; @@ -277,7 +275,7 @@ if (po->sk->state & PPPOX_CONNECTED) pppox_unbind_sock(po->sk); - + if (po->sk->state & PPPOX_CONNECTED) { lock_sock(po->sk); po->sk->shutdown = RCV_SHUTDOWN&SEND_SHUTDOWN; @@ -313,7 +311,7 @@ * Receive a PPPoE Session frame. * ***********************************************************************/ -static int pppoe_rcv(struct sk_buff *skb, +static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) @@ -336,6 +334,19 @@ skb_pull(skb, sizeof(struct pppoe_hdr)); ppp_input(&po->chan, skb); + } else if( sk->state & PPPOX_RELAY ){ + struct pppox_opt *relay_po; + + relay_po = get_item_by_addr( &po->pppoe_relay ); + + if( relay_po == NULL || + !( relay_po->sk->state & PPPOX_CONNECTED ) ) + goto abort; + + skb_pull(skb, sizeof(struct pppoe_hdr)); + if( !__pppoe_xmit( relay_po->sk , skb) ) + goto abort; + } else { sock_queue_rcv_skb(sk, skb); } @@ -353,7 +364,7 @@ * -- This is solely for detection of PADT frames * ***********************************************************************/ -static int pppoe_disc_rcv(struct sk_buff *skb, +static int pppoe_disc_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) @@ -539,7 +550,7 @@ dev = dev_get_by_name(sp->sa_addr.pppoe.dev); - error = -ENODEV; + error = -ENODEV; if (!dev) goto end; @@ -768,13 +779,11 @@ /************************************************************************ * - * xmit function called by generic PPP driver - * sends PPP frame over PPPoE socket + * xmit function for internal use. * ***********************************************************************/ -int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb) +int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) { - struct sock *sk = (struct sock *) chan->private; struct net_device *dev = sk->protinfo.pppox->pppoe_dev; struct pppoe_hdr hdr; struct pppoe_hdr *ph; @@ -832,6 +841,20 @@ abort: return 0; } + + +/************************************************************************ + * + * xmit function called by generic PPP driver + * sends PPP frame over PPPoE socket + * + ***********************************************************************/ +int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb) +{ + struct sock *sk = (struct sock *) chan->private; + return __pppoe_xmit(sk, skb); +} + struct ppp_channel_ops pppoe_chan_ops = { pppoe_xmit , NULL }; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/setup.c linux/drivers/net/setup.c --- v2.3.99-pre8/linux/drivers/net/setup.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/net/setup.c Tue May 23 08:21:51 2000 @@ -12,7 +12,6 @@ extern int slip_init_ctrl_dev(void); extern int strip_init_ctrl_dev(void); extern int x25_asy_init_ctrl_dev(void); -extern int slhc_install(void); extern int dmascc_init(void); extern int yam_init(void); @@ -22,7 +21,7 @@ extern int awc4500_pnp_probe(void); extern int awc4500_365_probe(void); extern int arcnet_init(void); -extern int cpm_enet_init(void); +extern int scc_enet_init(void); extern int dlci_setup(void); extern int lapbeth_init(void); extern int sdla_setup(void); @@ -34,7 +33,7 @@ extern int madgemc_probe(void); extern int tms_pci_probe(void); -/* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is tring of 9 zeros. */ +/* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is string of 9 zeros. */ #define __PAD6 "\0\0\0\0\0\0\0\0\0" #define __PAD5 __PAD6 "\0" #define __PAD4 __PAD5 "\0" @@ -73,27 +72,17 @@ #if defined(CONFIG_ARCNET) {arcnet_init, 0}, #endif -#if defined(CONFIG_8xx) - {cpm_enet_init, 0}, +#if defined(CONFIG_SCC_ENET) + {scc_enet_init, 0}, #endif #if defined(CONFIG_COMX) {comx_init, 0}, -#endif /* - * SLHC if present needs attaching so other people see it - * even if not opened. - */ +#endif + #if defined(CONFIG_LANMEDIA) {lmc_setup, 0}, #endif -#ifdef CONFIG_INET -#if (defined(CONFIG_SLIP) && defined(CONFIG_SLIP_COMPRESSED)) \ - || defined(CONFIG_PPP) \ - || (defined(CONFIG_ISDN) && defined(CONFIG_ISDN_PPP)) - {slhc_install, 0}, -#endif -#endif - /* * * Wireless non-HAM diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/sgiseeq.c linux/drivers/net/sgiseeq.c --- v2.3.99-pre8/linux/drivers/net/sgiseeq.c Sat Feb 26 22:31:47 2000 +++ linux/drivers/net/sgiseeq.c Sat May 13 08:29:40 2000 @@ -1,4 +1,4 @@ -/* $Id: sgiseeq.c,v 1.9 1998/10/14 23:40:46 ralf Exp $ +/* $Id: sgiseeq.c,v 1.17 2000/03/27 23:02:57 ralf Exp $ * * sgiseeq.c: Seeq8003 ethernet driver for SGI machines. * @@ -694,15 +694,14 @@ char *ep; if (initialized) /* Already initialized? */ - return 0; + return 1; initialized++; - /* First get the ethernet address of the onboard - * interface from ARCS. + /* First get the ethernet address of the onboard interface from ARCS. * This is fragile; PROM doesn't like running from cache. - * On MIPS64 it crashes for some other, yet unknown reason. + * On MIPS64 it crashes for some other, yet unknown reason ... */ - ep = romvec->get_evar("eaddr"); + ep = ArcGetEnvironmentVariable("eaddr"); str2eaddr(onboard_eth_addr, ep); return sgiseeq_init(dev, (struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)), diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/sgiseeq.h linux/drivers/net/sgiseeq.h --- v2.3.99-pre8/linux/drivers/net/sgiseeq.h Sat Feb 26 22:31:47 2000 +++ linux/drivers/net/sgiseeq.h Sat May 13 08:29:40 2000 @@ -1,4 +1,4 @@ -/* $Id: sgiseeq.h,v 1.5 1999/12/04 03:59:03 ralf Exp $ +/* $Id: sgiseeq.h,v 1.4 1999/10/09 00:01:24 ralf Exp $ * sgiseeq.h: Defines for the Seeq8003 ethernet controller. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/sis900.c linux/drivers/net/sis900.c --- v2.3.99-pre8/linux/drivers/net/sis900.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/sis900.c Mon May 15 12:13:10 2000 @@ -79,7 +79,8 @@ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_900}, {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7016, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018} + PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018}, + {0,} }; MODULE_DEVICE_TABLE (pci, sis900_pci_tbl); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/slhc.c linux/drivers/net/slhc.c --- v2.3.99-pre8/linux/drivers/net/slhc.c Tue Nov 23 22:42:21 1999 +++ linux/drivers/net/slhc.c Tue May 23 08:21:51 2000 @@ -77,7 +77,6 @@ #include #include #include -#include #include #include #include @@ -749,12 +748,6 @@ void cleanup_module(void) { return; -} - -#else /* MODULE */ -int __init slhc_install(void) -{ - return 0; } #endif /* MODULE */ diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/starfire.c linux/drivers/net/starfire.c --- v2.3.99-pre8/linux/drivers/net/starfire.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/starfire.c Sat May 13 08:19:21 2000 @@ -211,7 +211,7 @@ static struct pci_device_id starfire_pci_tbl[] __devinitdata = { { 0x9004, 0x6915, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_6915 }, - { 0, }, + { 0, } }; MODULE_DEVICE_TABLE(pci, starfire_pci_tbl); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/stnic.c linux/drivers/net/stnic.c --- v2.3.99-pre8/linux/drivers/net/stnic.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/stnic.c Sat May 20 12:05:30 2000 @@ -0,0 +1,302 @@ +/* stnic.c : A SH7750 specific part of driver for NS DP83902A ST-NIC. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999 kaz Kojima + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "8390.h" + +#define byte unsigned char +#define half unsigned short +#define word unsigned int +#define vbyte volatile unsigned char +#define vhalf volatile unsigned short +#define vword volatile unsigned int + +#define STNIC_RUN 0x01 /* 1 == Run, 0 == reset. */ + +#define START_PG 0 /* First page of TX buffer */ +#define STOP_PG 128 /* Last page +1 of RX ring */ + +/* Alias */ +#define STNIC_CR E8390_CMD +#define PG0_RSAR0 EN0_RSARLO +#define PG0_RSAR1 EN0_RSARHI +#define PG0_RBCR0 EN0_RCNTLO +#define PG0_RBCR1 EN0_RCNTHI + +#define CR_RRD E8390_RREAD +#define CR_RWR E8390_RWRITE +#define CR_PG0 E8390_PAGE0 +#define CR_STA E8390_START +#define CR_RDMA E8390_NODMA + +/* FIXME! YOU MUST SET YOUR OWN ETHER ADDRESS. */ +static byte stnic_eadr[6] = +{0x00, 0xc0, 0x6e, 0x00, 0x00, 0x07}; + +static struct net_device *stnic_dev; + +static int stnic_open (struct net_device *dev); +static int stnic_close (struct net_device *dev); +static void stnic_reset (struct net_device *dev); +static void stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr, + int ring_page); +static void stnic_block_input (struct net_device *dev, int count, + struct sk_buff *skb , int ring_offset); +static void stnic_block_output (struct net_device *dev, int count, + const unsigned char *buf, int start_page); + +static void stnic_init (struct net_device *dev); + +/* SH7750 specific read/write io. */ +static inline void +STNIC_DELAY (void) +{ + vword trash; + trash = *(vword *) 0xa0000000; + trash = *(vword *) 0xa0000000; +} + +static inline byte +STNIC_READ (int reg) +{ + byte val; + + val = (*(vhalf *) (PA_83902 + ((reg) << 1)) >> 8) & 0xff; + STNIC_DELAY (); + return val; +} + +static inline void +STNIC_WRITE (int reg, byte val) +{ + *(vhalf *) (PA_83902 + ((reg) << 1)) = ((half) (val) << 8); + STNIC_DELAY (); +} + +int __init stnic_probe(void) +{ + struct net_device tmp, *dev = NULL; + int i; + + tmp.base_addr = 0x1000; + dev = &tmp; + + if (load_8390_module ("stnic.c")) + return -ENOSYS; + + /* New style probing API */ + dev = init_etherdev (0, 0); + stnic_dev = dev; + + /* Allocate dev->priv and fill in 8390 specific dev fields. */ + if (ethdev_init (dev)) + { + printk ("Unable to get memory for dev->priv.\n"); + return -ENOMEM; + } + + for (i = 0; i < ETHER_ADDR_LEN; i++) + dev->dev_addr[i] = stnic_eadr[i]; + + /* Set the base address to point to the NIC, not the "real" base! */ + dev->base_addr = 0x1000; + dev->irq = IRQ_STNIC; + dev->open = &stnic_open; + dev->stop = &stnic_close; + + /* Snarf the interrupt now. There's no point in waiting since we cannot + share and the board will usually be enabled. */ + if (request_irq (dev->irq, ei_interrupt, 0, "DP83902A", dev)) + { + printk (" unable to get IRQ %d.\n", dev->irq); + kfree(dev->priv); + dev->priv = NULL; + return EAGAIN; + } + + ei_status.name = "eth0"; + ei_status.word16 = 1; + ei_status.tx_start_page = START_PG; + ei_status.rx_start_page = START_PG + TX_PAGES; + ei_status.stop_page = STOP_PG; + + ei_status.reset_8390 = &stnic_reset; + ei_status.get_8390_hdr = &stnic_get_hdr; + ei_status.block_input = &stnic_block_input; + ei_status.block_output = &stnic_block_output; + stnic_init (dev); + + printk (KERN_INFO "NS ST-NIC 83902A\n"); + + return 0; +} + +static int +stnic_open (struct net_device *dev) +{ +#if 0 + printk ("stnic open\n"); +#endif + ei_open (dev); + MOD_INC_USE_COUNT; + return 0; +} + +static int +stnic_close (struct net_device *dev) +{ + ei_close (dev); + MOD_DEC_USE_COUNT; + return 0; +} + +static void +stnic_reset (struct net_device *dev) +{ + *(vhalf *) PA_83902_RST = 0; + udelay (5); + if (ei_debug > 1) + printk("8390 reset done (%ld).", jiffies); + *(vhalf *) PA_83902_RST = ~0; + udelay (5); +} + +static void +stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr, + int ring_page) +{ + half buf[2]; + + STNIC_WRITE (PG0_RSAR0, 0); + STNIC_WRITE (PG0_RSAR1, ring_page); + STNIC_WRITE (PG0_RBCR0, 4); + STNIC_WRITE (PG0_RBCR1, 0); + STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA); + + buf[0] = *(vhalf *) PA_83902_IF; + STNIC_DELAY (); + buf[1] = *(vhalf *) PA_83902_IF; + STNIC_DELAY (); + hdr->next = buf[0] >> 8; + hdr->status = buf[0] & 0xff; +#ifdef __LITTLE_ENDIAN__ + hdr->count = buf[1]; +#else + hdr->count = ((buf[1] >> 8) & 0xff) | (buf[1] << 8); +#endif + + if (ei_debug > 1) + printk ("ring %x status %02x next %02x count %04x.\n", + ring_page, hdr->status, hdr->next, hdr->count); + + STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA); +} + +/* Block input and output, similar to the Crynwr packet driver. If you are + porting to a new ethercard look at the packet driver source for hints. + The HP LAN doesn't use shared memory -- we put the packet + out through the "remote DMA" dataport. */ + +static void +stnic_block_input (struct net_device *dev, int length, struct sk_buff *skb, + int offset) +{ + char *buf = skb->data; + half val; + + STNIC_WRITE (PG0_RSAR0, offset & 0xff); + STNIC_WRITE (PG0_RSAR1, offset >> 8); + STNIC_WRITE (PG0_RBCR0, length & 0xff); + STNIC_WRITE (PG0_RBCR1, length >> 8); + STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA); + + if (length & 1) + length++; + + while (length > 0) + { + val = *(vhalf *) PA_83902_IF; +#ifdef __LITTLE_ENDIAN__ + *buf++ = val & 0xff; + *buf++ = val >> 8; +#else + *buf++ = val >> 8; + *buf++ = val & 0xff; +#endif + STNIC_DELAY (); + length -= sizeof (half); + } + + STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA); +} + +static void +stnic_block_output (struct net_device *dev, int length, + const unsigned char *buf, int output_page) +{ + + STNIC_WRITE (PG0_RBCR0, 1); + STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA); + + STNIC_WRITE (PG0_RSAR0, 0); + STNIC_WRITE (PG0_RSAR1, output_page); + STNIC_WRITE (PG0_RBCR0, length & 0xff); + STNIC_WRITE (PG0_RBCR1, length >> 8); + STNIC_WRITE (STNIC_CR, CR_RWR | CR_PG0 | CR_STA); + + if (length & 1) + length++; + + while (length > 0) + { +#ifdef __LITTLE_ENDIAN__ + *(vhalf *) PA_83902_IF = ((half) buf[1] << 8) | buf[0]; +#else + *(vhalf *) PA_83902_IF = ((half) buf[0] << 8) | buf[1]; +#endif + STNIC_DELAY (); + buf += sizeof (half); + length -= sizeof (half); + } + + STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA); +} + +/* This function resets the STNIC if something screws up. */ +static void +stnic_init (struct net_device *dev) +{ + stnic_reset (dev); + NS8390_init (dev, 0); + return; +} + +/* Hardware interrupt handler. */ +extern void ei_interrupt (int irq, void *dev_id, struct pt_regs *regs); + +void +do_stnic_intr (int irq, void *dev_id, struct pt_regs *regs) +{ + ei_interrupt (0, stnic_dev, regs); +} + +module_init(stnic_probe); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c --- v2.3.99-pre8/linux/drivers/net/tulip/tulip_core.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/tulip/tulip_core.c Sat May 13 08:19:21 2000 @@ -168,7 +168,7 @@ { 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 }, { 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 }, { 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 }, - {0}, + {0, } }; MODULE_DEVICE_TABLE(pci, tulip_pci_tbl); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c --- v2.3.99-pre8/linux/drivers/net/via-rhine.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/via-rhine.c Sat May 13 08:19:21 2000 @@ -291,7 +291,7 @@ { {0x1106, 0x6100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT86C100A}, {0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT3043}, - {0,}, /* terminate list */ + {0,} /* terminate list */ }; MODULE_DEVICE_TABLE(pci, via_rhine_pci_tbl); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wan/comx-hw-comx.c linux/drivers/net/wan/comx-hw-comx.c --- v2.3.99-pre8/linux/drivers/net/wan/comx-hw-comx.c Tue Mar 14 19:10:39 2000 +++ linux/drivers/net/wan/comx-hw-comx.c Sun May 21 20:34:37 2000 @@ -1031,11 +1031,6 @@ char *page; - if (file->f_dentry->d_inode->i_ino != entry->low_ino) { - printk(KERN_ERR "comx_write_proc: file <-> data internal error\n"); - return -EIO; - } - if(ch->init_status & HW_OPEN) { return -EAGAIN; } @@ -1234,7 +1229,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &comxhw_read_proc; new_file->write_proc = &comxhw_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->size = 6; new_file->nlink = 1; @@ -1245,7 +1239,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &comxhw_read_proc; new_file->write_proc = &comxhw_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->size = 5; new_file->nlink = 1; @@ -1256,7 +1249,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &comxhw_read_proc; new_file->write_proc = &comxhw_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->size = 2; // Ezt tudjuk new_file->nlink = 1; @@ -1268,7 +1260,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &comxhw_read_proc; new_file->write_proc = &comxhw_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->size = 9; new_file->nlink = 1; } @@ -1280,7 +1271,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &comxhw_read_proc; new_file->write_proc = &comxhw_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->size = 8; new_file->nlink = 1; @@ -1291,7 +1281,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &comxhw_read_proc; new_file->write_proc = NULL; - new_file->proc_iops = &comx_normal_inode_ops; new_file->nlink = 1; if ((new_file = create_proc_entry(FILENAME_FIRMWARE, S_IFREG | 0644, @@ -1301,7 +1290,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &comxhw_read_proc; new_file->write_proc = &comxhw_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->nlink = 1; if (ch->hardware == &comx_hw) { diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wan/comx-hw-locomx.c linux/drivers/net/wan/comx-hw-locomx.c --- v2.3.99-pre8/linux/drivers/net/wan/comx-hw-locomx.c Tue Mar 14 19:10:39 2000 +++ linux/drivers/net/wan/comx-hw-locomx.c Sun May 21 20:34:37 2000 @@ -330,11 +330,6 @@ int val; char *page; - if (file->f_dentry->d_inode->i_ino != entry->low_ino) { - printk(KERN_ERR "hw_write_proc: file <-> data internal error\n"); - return -EIO; - } - if (!(page = (char *)__get_free_page(GFP_KERNEL))) { return -ENOMEM; } @@ -395,7 +390,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &locomx_read_proc; new_file->write_proc = &locomx_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->nlink = 1; if ((new_file = create_proc_entry(FILENAME_IRQ, S_IFREG | 0644, @@ -405,7 +399,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &locomx_read_proc; new_file->write_proc = &locomx_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->nlink = 1; /* No clock yet */ @@ -417,7 +410,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &locomx_read_proc; new_file->write_proc = &locomx_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->nlink = 1; */ diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wan/comx-hw-mixcom.c linux/drivers/net/wan/comx-hw-mixcom.c --- v2.3.99-pre8/linux/drivers/net/wan/comx-hw-mixcom.c Tue Mar 14 19:10:39 2000 +++ linux/drivers/net/wan/comx-hw-mixcom.c Sun May 21 20:34:37 2000 @@ -742,11 +742,6 @@ char *page; int value; - if (file->f_dentry->d_inode->i_ino != entry->low_ino) { - printk(KERN_ERR "mixcom_write_proc: file <-> data internal error\n"); - return -EIO; - } - if (!(page = (char *)__get_free_page(GFP_KERNEL))) { return -ENOMEM; } @@ -829,7 +824,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &mixcom_read_proc; new_file->write_proc = &mixcom_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->nlink = 1; if ((new_file = create_proc_entry(FILENAME_IRQ, S_IFREG | 0644, @@ -839,7 +833,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &mixcom_read_proc; new_file->write_proc = &mixcom_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->nlink = 1; #if 0 @@ -850,7 +843,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &mixcom_read_proc; new_file->write_proc = &mixcom_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->nlink = 1; #endif @@ -861,7 +853,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &mixcom_read_proc; new_file->write_proc = &mixcom_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->nlink = 1; if ((new_file = create_proc_entry(FILENAME_TWIN, S_IFREG | 0444, @@ -871,7 +862,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &mixcom_read_proc; new_file->write_proc = &mixcom_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->nlink = 1; setup_twin(dev); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wan/comx-proto-fr.c linux/drivers/net/wan/comx-proto-fr.c --- v2.3.99-pre8/linux/drivers/net/wan/comx-proto-fr.c Tue Mar 14 19:10:39 2000 +++ linux/drivers/net/wan/comx-proto-fr.c Sun May 21 20:34:37 2000 @@ -641,11 +641,6 @@ fr = ch->LINE_privdata; } - if (file->f_dentry->d_inode->i_ino != entry->low_ino) { - printk(KERN_ERR "comxfr_write_proc: file <-> data internal error\n"); - return -EIO; - } - if (!(page = (char *)__get_free_page(GFP_KERNEL))) { return -ENOMEM; } @@ -803,7 +798,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &fr_read_proc; new_file->write_proc = &fr_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->size = 5; new_file->nlink = 1; @@ -814,7 +808,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &fr_read_proc; new_file->write_proc = &fr_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->size = 4; new_file->nlink = 1; @@ -860,7 +853,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &fr_read_proc; new_file->write_proc = &fr_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->size = 5; new_file->nlink = 1; @@ -871,7 +863,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &fr_read_proc; new_file->write_proc = &fr_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->size = 10; new_file->nlink = 1; MOD_INC_USE_COUNT; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wan/comx-proto-lapb.c linux/drivers/net/wan/comx-proto-lapb.c --- v2.3.99-pre8/linux/drivers/net/wan/comx-proto-lapb.c Tue Mar 14 19:10:39 2000 +++ linux/drivers/net/wan/comx-proto-lapb.c Sun May 21 20:34:37 2000 @@ -221,11 +221,6 @@ unsigned long parm; char *page; - if (file->f_dentry->d_inode->i_ino != entry->low_ino) { - printk(KERN_ERR "comxlapb_write_proc: file <-> data internal error\n"); - return -EIO; - } - if (lapb_getparms(dev->priv, &parms)) { return -ENODEV; } @@ -499,7 +494,6 @@ new_file->data = (void *)new_file; new_file->read_proc = &comxlapb_read_proc; new_file->write_proc = &comxlapb_write_proc; - new_file->proc_iops = &comx_normal_inode_ops; new_file->size = size; new_file->nlink = 1; } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wan/comx.c linux/drivers/net/wan/comx.c --- v2.3.99-pre8/linux/drivers/net/wan/comx.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/wan/comx.c Sun May 21 20:34:37 2000 @@ -81,21 +81,18 @@ static struct comx_hardware *comx_channels = NULL; static struct comx_protocol *comx_lines = NULL; -struct inode_operations comx_normal_inode_ops; -static struct inode_operations comx_root_inode_ops; // for mkdir -static struct inode_operations comx_debug_inode_ops; // mas a file_ops -static struct file_operations comx_normal_file_ops; // with open/relase -static struct file_operations comx_debug_file_ops; // with lseek+read +static struct inode_operations comx_root_inode_ops = { + lookup: comx_lookup, + mkdir: comx_mkdir, + rmdir: comx_rmdir, +}; -static void comx_delete_dentry(struct dentry *dentry); +static int comx_delete_dentry(struct dentry *dentry); static struct proc_dir_entry *create_comx_proc_entry(char *name, int mode, int size, struct proc_dir_entry *dir); static struct dentry_operations comx_dentry_operations = { - NULL, /* revalidate */ - NULL, /* d_hash */ - NULL, /* d_compare */ - &comx_delete_dentry /* d_delete */ + d_delete: comx_delete_dentry, }; @@ -601,11 +598,6 @@ char str[30]; int ret=0; - if (file->f_dentry->d_inode->i_ino != entry->low_ino) { - printk(KERN_ERR "comx_write_proc: file <-> data internal error\n"); - return -EIO; - } - if (count > PAGE_SIZE) { printk(KERN_ERR "count is %lu > %d!!!\n", count, (int)PAGE_SIZE); return -ENOSPC; @@ -761,84 +753,12 @@ return count; } -static loff_t comx_debug_lseek(struct file *file, loff_t offset, int orig) -{ - switch(orig) { - case 0: - file->f_pos = max(0, min(offset, - file->f_dentry->d_inode->i_size)); - return(file->f_pos); - case 1: - file->f_pos = max(0, min(offset + file->f_pos, - file->f_dentry->d_inode->i_size)); - return(file->f_pos); - case 2: - file->f_pos = max(0, - min(offset + file->f_dentry->d_inode->i_size, - file->f_dentry->d_inode->i_size)); - return(file->f_pos); - } - return(file->f_pos); -} - -static int comx_file_open(struct inode *inode, struct file *file) -{ - - if((file->f_mode & FMODE_WRITE) && !(inode->i_mode & 0200)) { - return -EACCES; - } - - MOD_INC_USE_COUNT; - return 0; -} - -static int comx_file_release(struct inode *inode, struct file *file) -{ - MOD_DEC_USE_COUNT; - return 0; -} - -static ssize_t comx_debug_read(struct file *file, char *buffer, size_t count, - loff_t *ppos) -{ - struct proc_dir_entry *de = file->f_dentry->d_inode->u.generic_ip; - struct net_device *dev = de->parent->data; - struct comx_channel *ch = dev->priv; - loff_t copied = 0; - unsigned long flags; - - save_flags(flags); cli(); // We may run into trouble when debug_area is filled - // from irq inside read. no problem if the buffer is - // large enough - - while (count > 0 && ch->debug_start != ch->debug_end) { - int len; - - len = min( (ch->debug_end - ch->debug_start + ch->debug_size) - %ch->debug_size, min (ch->debug_size - - ch->debug_start, count)); - - if (len) copy_to_user(buffer + copied, - ch->debug_area + ch->debug_start, len); - ch->debug_start = (ch->debug_start + len) % ch->debug_size; - - de->size -= len; - count -= len; - copied += len; - } - - restore_flags(flags); - return copied; -} - static int comx_mkdir(struct inode *dir, struct dentry *dentry, int mode) { struct proc_dir_entry *new_dir, *debug_file; struct net_device *dev; struct comx_channel *ch; - if (dir->i_ino != comx_root_dir->low_ino) return -ENOTDIR; - if ((new_dir = create_proc_entry(dentry->d_name.name, mode | S_IFDIR, comx_root_dir)) == NULL) { return -EIO; @@ -867,7 +787,6 @@ S_IFREG | 0644, new_dir)) == NULL) { return -ENOMEM; } - debug_file->proc_iops = &comx_debug_inode_ops; debug_file->data = (void *)debug_file; debug_file->read_proc = NULL; // see below debug_file->write_proc = &comx_write_proc; @@ -912,9 +831,6 @@ struct comx_channel *ch = dev->priv; int ret; - /* Egyelore miert ne ? */ - if (dir->i_ino != comx_root_dir->low_ino) return -ENOTDIR; - if (dev->flags & IFF_UP) { printk(KERN_ERR "%s: down interface before removing it\n", dev->name); return -EBUSY; @@ -962,10 +878,6 @@ struct proc_dir_entry *de; struct inode *inode = NULL; - if (!dir || !S_ISDIR(dir->i_mode)) { - return ERR_PTR(-ENOTDIR); - } - if ((de = (struct proc_dir_entry *) dir->u.generic_ip) != NULL) { for (de = de->subdir ; de ; de = de->next) { if ((de && de->low_ino) && @@ -998,9 +910,9 @@ return __res; } -static void comx_delete_dentry(struct dentry *dentry) +static int comx_delete_dentry(struct dentry *dentry) { - d_drop(dentry); + return 1; } static struct proc_dir_entry *create_comx_proc_entry(char *name, int mode, @@ -1009,7 +921,6 @@ struct proc_dir_entry *new_file; if ((new_file = create_proc_entry(name, S_IFREG | mode, dir)) != NULL) { - new_file->proc_iops = &comx_normal_inode_ops; new_file->data = (void *)new_file; new_file->read_proc = &comx_read_proc; new_file->write_proc = &comx_write_proc; @@ -1115,23 +1026,6 @@ { struct proc_dir_entry *new_file; - comx_root_inode_ops.lookup = &comx_lookup; - comx_root_inode_ops.mkdir = &comx_mkdir; - comx_root_inode_ops.rmdir = &comx_rmdir; - - comx_normal_inode_ops.lookup = &comx_lookup; - - memcpy(&comx_debug_inode_ops, &comx_normal_inode_ops, - sizeof(struct inode_operations)); - - comx_normal_file_ops.open = &comx_file_open; - comx_normal_file_ops.release = &comx_file_release; - - memcpy(&comx_debug_file_ops, &comx_normal_file_ops, - sizeof(struct file_operations)); - comx_debug_file_ops.llseek = &comx_debug_lseek; - comx_debug_file_ops.read = &comx_debug_read; - comx_root_dir = create_proc_entry("comx", S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, &proc_root); if (!comx_root_dir) @@ -1143,7 +1037,6 @@ return -ENOMEM; } - new_file->proc_iops = &comx_normal_inode_ops; new_file->data = new_file; new_file->read_proc = &comx_root_read_proc; new_file->write_proc = NULL; @@ -1154,7 +1047,6 @@ return -ENOMEM; } - new_file->proc_iops = &comx_normal_inode_ops; new_file->data = new_file; new_file->read_proc = &comx_root_read_proc; new_file->write_proc = NULL; @@ -1211,5 +1103,4 @@ EXPORT_SYMBOL(comx_status); EXPORT_SYMBOL(comx_rx); EXPORT_SYMBOL(comx_strcasecmp); -EXPORT_SYMBOL(comx_normal_inode_ops); EXPORT_SYMBOL(comx_root_dir); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wan/lmc/lmc_main.c linux/drivers/net/wan/lmc/lmc_main.c --- v2.3.99-pre8/linux/drivers/net/wan/lmc/lmc_main.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/wan/lmc/lmc_main.c Sat May 13 08:19:21 2000 @@ -112,7 +112,7 @@ #ifdef MODULE static struct pci_device_id lmc_pci_tbl[] __devinitdata = { { 0x1011, 0x009, 0x1379, PCI_ANY_ID, 0, 0, 0}, - { 0 }, + { 0, } }; MODULE_DEVICE_TABLE(pci, lmc_pci_tbl); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c --- v2.3.99-pre8/linux/drivers/net/wavelan.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/wavelan.c Sun May 21 20:18:08 2000 @@ -4211,6 +4211,7 @@ break; } memset(dev, 0x00, sizeof(struct net_device)); + memcpy(dev->name, name[i], IFNAMSIZ); /* Copy name */ dev->base_addr = io[i]; dev->irq = irq[i]; dev->init = &wavelan_config; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wavelan.p.h linux/drivers/net/wavelan.p.h --- v2.3.99-pre8/linux/drivers/net/wavelan.p.h Thu May 11 15:30:07 2000 +++ linux/drivers/net/wavelan.p.h Sun May 21 20:18:08 2000 @@ -695,8 +695,10 @@ /* Parameters set by insmod */ static int io[4] = { 0, 0, 0, 0 }; static int irq[4] = { 0, 0, 0, 0 }; +static char name[4][IFNAMSIZ] = { "", "", "", "" }; MODULE_PARM(io, "1-4i"); MODULE_PARM(irq, "1-4i"); +MODULE_PARM(name, "1-4c" __MODULE_STRING(IFNAMSIZ)); #endif /* MODULE */ #endif /* WAVELAN_P_H */ diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c --- v2.3.99-pre8/linux/drivers/net/yellowfin.c Thu May 11 15:30:07 2000 +++ linux/drivers/net/yellowfin.c Sat May 13 08:19:21 2000 @@ -237,7 +237,7 @@ static struct pci_device_id yellowfin_pci_tbl[] __devinitdata = { { 0x1000, 0x0702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, YELLOWFIN_GNIC }, { 0x1000, 0x0701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SYM83C885 }, - { 0, }, + { 0, } }; MODULE_DEVICE_TABLE (pci, yellowfin_pci_tbl); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog --- v2.3.99-pre8/linux/drivers/parport/ChangeLog Wed Apr 26 16:34:08 2000 +++ linux/drivers/parport/ChangeLog Tue May 23 08:24:46 2000 @@ -1,3 +1,43 @@ +2000-05-16 Tim Waugh + + * share.c (parport_claim): Fix SMP race. + +2000-05-15 Gunther Mayer + + * parport_pc.c (parport_pc_compat_write_block_pio): Check for + timeouts. + (parport_pc_ecp_write_block_pio): Likewise. + (parport_pc_ecp_read_block_pio): Likewise. + +2000-05-02 Gunther Mayer + + * parport_pc.c: PCI SYBA patch and verbose PCI detection. + +2000-05-02 Gunther Mayer + + * parport_pc.c (decode_smsc): Fix SMSC 665/666 identification. + +2000-04-28 Tim Waugh + + * ieee1284.c: Short function descriptions can't be multiline. + + * daisy.c: Short function descriptions can't be multiline. + +2000-04-19 Tim Waugh + + * parport_pc.c (parport_pc_fifo_write_block_dma): Make maxlen + calculation a bit clearer. + + * ieee1284.c (parport_negotiate): Turn on data line drivers. + + * ieee1284_ops.c (parport_ieee1284_read_byte): Turn off data line + drivers. + (parport_ieee1284_write_compat): Turn on data line drivers. + + * daisy.c (assign_addrs): Turn on data line drivers. + (cpp_mux): Likewise. + (cpp_daisy): Likewise. + 2000-04-04 Tim Waugh * parport_pc.c: Add support for another PCI card. diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/parport/daisy.c linux/drivers/parport/daisy.c --- v2.3.99-pre8/linux/drivers/parport/daisy.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/parport/daisy.c Mon May 15 11:16:30 2000 @@ -252,8 +252,7 @@ } /** - * parport_device_num - convert device coordinates into a - * canonical device number + * parport_device_num - convert device coordinates * @parport: parallel port number * @mux: multiplexor port number (-1 for no multiplexor) * @daisy: daisy chain address (-1 for no daisy chain address) @@ -279,8 +278,7 @@ } /** - * parport_device_coords - convert a canonical device number into - * device coordinates + * parport_device_coords - convert canonical device number * @devnum: device number * @parport: pointer to storage for parallel port number * @mux: pointer to storage for multiplexor port number @@ -325,6 +323,7 @@ { unsigned char s; + parport_data_forward (port); parport_write_data (port, 0xaa); udelay (2); parport_write_data (port, 0x55); udelay (2); parport_write_data (port, 0x00); udelay (2); @@ -373,6 +372,7 @@ unsigned char s; int rc; + parport_data_forward (port); parport_write_data (port, 0xaa); udelay (2); parport_write_data (port, 0x55); udelay (2); parport_write_data (port, 0xf0); udelay (2); @@ -430,6 +430,7 @@ int thisdev = numdevs; char *deviceid; + parport_data_forward (port); parport_write_data (port, 0xaa); udelay (2); parport_write_data (port, 0x55); udelay (2); parport_write_data (port, 0x00); udelay (2); @@ -502,8 +503,7 @@ 'from' itself is skipped. */ /** - * parport_find_device - find a device with a specified - * manufacturer and model string + * parport_find_device - find a specific device * @mfg: required manufacturer string * @mdl: required model string * @from: previous device number found in search, or %NULL for diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/parport/ieee1284.c linux/drivers/parport/ieee1284.c --- v2.3.99-pre8/linux/drivers/parport/ieee1284.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/parport/ieee1284.c Mon May 15 11:16:30 2000 @@ -380,6 +380,7 @@ udelay(1); /* Event 0: Set data */ + parport_data_forward (port); parport_write_data (port, m); udelay (400); /* Shouldn't need to wait this long. */ @@ -734,7 +735,6 @@ /** * parport_set_timeout - set the inactivity timeout for a device - * on a port * @dev: device on a port * @inactivity: inactivity timeout (in jiffies) * diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/parport/ieee1284_ops.c linux/drivers/parport/ieee1284_ops.c --- v2.3.99-pre8/linux/drivers/parport/ieee1284_ops.c Thu Feb 10 17:11:12 2000 +++ linux/drivers/parport/ieee1284_ops.c Mon May 15 11:16:30 2000 @@ -57,6 +57,7 @@ port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; parport_write_control (port, ctl); + parport_data_forward (port); while (count < len) { long expire = jiffies + dev->timeout; long wait = (HZ + 99) / 100; @@ -267,6 +268,9 @@ port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE; break; } + + /* Event 14: Place data bus in high impedance state. */ + parport_data_reverse (port); /* Event 7: Set nAutoFd low. */ parport_frob_control (port, diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c --- v2.3.99-pre8/linux/drivers/parport/parport_pc.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/parport/parport_pc.c Mon May 15 11:18:19 2000 @@ -704,6 +704,7 @@ int flags) { size_t written; + int r; /* Special case: a timeout of zero means we cannot call schedule(). */ if (!port->physport->cad->timeout) @@ -745,9 +746,14 @@ frob_econtrol (port, 0xe0, ECR_PS2 << 5); } - parport_wait_peripheral (port, - PARPORT_STATUS_BUSY, - PARPORT_STATUS_BUSY); + r = parport_wait_peripheral (port, + PARPORT_STATUS_BUSY, + PARPORT_STATUS_BUSY); + if (r) + printk (KERN_DEBUG + "%s: BUSY timeout (%d) in compat_write_block_pio\n", + port->name, r); + port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE; return written; @@ -760,6 +766,7 @@ int flags) { size_t written; + int r; /* Special case: a timeout of zero means we cannot call schedule(). */ if (!port->physport->cad->timeout) @@ -772,9 +779,12 @@ parport_frob_control (port, PARPORT_CONTROL_INIT, 0); /* Event 40: PError goes high. */ - parport_wait_peripheral (port, - PARPORT_STATUS_PAPEROUT, - PARPORT_STATUS_PAPEROUT); + r = parport_wait_peripheral (port, + PARPORT_STATUS_PAPEROUT, + PARPORT_STATUS_PAPEROUT); + if (r) + printk (KERN_DEBUG "%s: PError timeout (%d) " + "in ecp_write_block_pio\n", port->name, r); } /* Set up ECP parallel port mode.*/ @@ -818,18 +828,30 @@ parport_pc_data_reverse (port); /* Must be in PS2 mode */ udelay (5); parport_frob_control (port, PARPORT_CONTROL_INIT, 0); - parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0); + r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0); + if (r) + printk (KERN_DEBUG "%s: PE,1 timeout (%d) " + "in ecp_write_block_pio\n", port->name, r); + parport_frob_control (port, PARPORT_CONTROL_INIT, PARPORT_CONTROL_INIT); - parport_wait_peripheral (port, - PARPORT_STATUS_PAPEROUT, - PARPORT_STATUS_PAPEROUT); + r = parport_wait_peripheral (port, + PARPORT_STATUS_PAPEROUT, + PARPORT_STATUS_PAPEROUT); + if (r) + printk (KERN_DEBUG "%s: PE,2 timeout (%d) " + "in ecp_write_block_pio\n", port->name, r); } - parport_wait_peripheral (port, - PARPORT_STATUS_BUSY, - PARPORT_STATUS_BUSY); + r = parport_wait_peripheral (port, + PARPORT_STATUS_BUSY, + PARPORT_STATUS_BUSY); + if(r) + printk (KERN_DEBUG + "%s: BUSY timeout (%d) in ecp_write_block_pio\n", + port->name, r); + port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE; return written; @@ -840,6 +862,7 @@ { size_t left = length; size_t fifofull; + int r; const int fifo = FIFO(port); const struct parport_pc_private *priv = port->physport->private_data; const int fifo_depth = priv->fifo_depth; @@ -882,7 +905,10 @@ 0); /* Event 40: PError goes low */ - parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0); + r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0); + if (r) + printk (KERN_DEBUG "%s: PE timeout Event 40 (%d) " + "in ecp_read_block_pio\n", port->name, r); } /* Set up ECP FIFO mode.*/ @@ -961,9 +987,14 @@ /* Go to forward idle mode to shut the peripheral up. */ parport_frob_control (port, PARPORT_CONTROL_INIT, 0); - parport_wait_peripheral (port, - PARPORT_STATUS_PAPEROUT, - PARPORT_STATUS_PAPEROUT); + r = parport_wait_peripheral (port, + PARPORT_STATUS_PAPEROUT, + PARPORT_STATUS_PAPEROUT); + if (r) + printk (KERN_DEBUG + "%s: PE timeout FWDIDLE (%d) in ecp_read_block_pio\n", + port->name, r); + port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; /* Finish up. */ @@ -1218,7 +1249,7 @@ if (devid == devrev) /* simple heuristics, we happened to read some - non-winbond register */ + non-smsc register */ return; func=NULL; @@ -1228,8 +1259,8 @@ if (id==0x0302) {type="37c669"; func=show_parconfig_smsc37c669;} else if (id==0x6582) type="37c665IR"; - else if ((id==0x6502) && (key==0x44)) type="37c665GT"; - else if ((id==0x6502) && (key==0x55)) type="37c666GT"; + else if (devid==0x65) type="37c665GT"; + else if (devid==0x66) type="37c666GT"; if(type==NULL) printk("SMSC unknown chip type\n"); @@ -2263,6 +2294,7 @@ plx_9050, afavlab_tk9902, timedia_1889, + syba_2p_epp, }; @@ -2270,9 +2302,11 @@ * (but offset by last_sio) */ static struct parport_pc_pci { int numports; - struct { + struct { /* BAR (base address registers) numbers in the config + space header */ int lo; - int hi; /* -ve if not there */ + int hi; /* -1 if not there, >6 for offset-method (max + BAR is 6) */ } addr[4]; } cards[] __devinitdata = { /* siig_1s1p_10x_550 */ { 1, { { 3, 4 }, } }, @@ -2301,6 +2335,9 @@ /* plx_9050 */ { 2, { { 4, -1 }, { 5, -1 }, } }, /* afavlab_tk9902 */ { 1, { { 0, 1 }, } }, /* timedia_1889 */ { 1, { { 2, -1 }, } }, + /* SYBA uses fixed offsets in + a 1K io window */ + /* syba_2p_epp */ { 2, { { 0, 0x078 }, { 0, 0x178 }, } }, }; static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = { @@ -2360,7 +2397,8 @@ PCI_ANY_ID, PCI_ANY_ID, 0, 0, afavlab_tk9902 }, { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889, PCI_ANY_ID, PCI_ANY_ID, 0, 0, timedia_1889 }, - { 0, }, /* terminate list */ + { 0x1592, 0x0782, PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_2p_epp }, + { 0, } /* terminate list */ }; MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl); @@ -2384,9 +2422,16 @@ unsigned long io_lo, io_hi; io_lo = pci_resource_start (dev, lo); io_hi = 0; - if (hi >= 0) + if ((hi >= 0) && (hi <= 6)) io_hi = pci_resource_start (dev, hi); + else if (hi > 6) + io_lo += hi; /* Reinterpret the meaning of + "hi" as an offset (see SYBA + def.) */ /* TODO: test if sharing interrupts works */ + printk (KERN_DEBUG "PCI parallel port detected: %04x:%04x, " + "I/O at %#lx(%#lx)\n", parport_pc_pci_tbl[i].vendor, + parport_pc_pci_tbl[i].device, io_lo, io_hi); if (parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, dev)) count++; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/parport/share.c linux/drivers/parport/share.c --- v2.3.99-pre8/linux/drivers/parport/share.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/parport/share.c Mon May 22 09:50:55 2000 @@ -602,6 +602,7 @@ void parport_unregister_device(struct pardevice *dev) { struct parport *port; + unsigned long flags; #ifdef PARPORT_PARANOID if (dev == NULL) { @@ -614,11 +615,14 @@ port = dev->port->physport; + read_lock_irqsave (&port->cad_lock, flags); if (port->cad == dev) { + read_unlock_irqrestore (&port->cad_lock, flags); printk(KERN_DEBUG "%s: %s forgot to release port\n", port->name, dev->name); parport_release (dev); } + read_unlock_irqrestore (&port->cad_lock, flags); spin_lock(&port->pardevice_lock); if (dev->next) @@ -663,14 +667,17 @@ struct parport *port = dev->port->physport; unsigned long flags; + read_lock_irqsave (&port->cad_lock, flags); if (port->cad == dev) { + read_unlock_irqrestore (&port->cad_lock, flags); printk(KERN_INFO "%s: %s already owner\n", dev->port->name,dev->name); return 0; } + read_unlock_irqrestore (&port->cad_lock, flags); -try_again: /* Preempt any current device */ + write_lock_irqsave (&port->cad_lock, flags); if ((oldcad = port->cad) != NULL) { if (oldcad->preempt) { if (oldcad->preempt(oldcad->private)) @@ -680,7 +687,9 @@ goto blocked; if (port->cad != oldcad) { - printk(KERN_WARNING + /* I think we'll actually deadlock rather than + get here, but just in case.. */ + printk(KERN_WARNING "%s: %s released port when preempted!\n", port->name, oldcad->name); if (port->cad) @@ -707,9 +716,7 @@ } /* Now we do the change of devices */ - write_lock_irqsave(&port->cad_lock, flags); port->cad = dev; - write_unlock_irqrestore(&port->cad_lock, flags); #ifdef CONFIG_PARPORT_1284 /* If it's a mux port, select it. */ @@ -729,6 +736,7 @@ /* Restore control registers */ port->ops->restore_state(port, dev->state); + write_unlock_irqrestore(&port->cad_lock, flags); dev->time = jiffies; return 0; @@ -736,13 +744,10 @@ /* If this is the first time we tried to claim the port, register an interest. This is only allowed for devices sleeping in parport_claim_or_block(), or those with a wakeup function. */ + + /* The cad_lock is still held for writing here */ if (dev->waiting & 2 || dev->wakeup) { - spin_lock_irqsave (&port->waitlist_lock, flags); - if (port->cad == NULL) { - /* The port got released in the meantime. */ - spin_unlock_irqrestore (&port->waitlist_lock, flags); - goto try_again; - } + spin_lock (&port->waitlist_lock); if (test_and_set_bit(0, &dev->waiting) == 0) { /* First add ourselves to the end of the wait list. */ dev->waitnext = NULL; @@ -753,8 +758,9 @@ } else port->waithead = port->waittail = dev; } - spin_unlock_irqrestore (&port->waitlist_lock, flags); + spin_unlock (&port->waitlist_lock); } + write_unlock_irqrestore (&port->cad_lock, flags); return -EAGAIN; } @@ -826,7 +832,9 @@ unsigned long flags; /* Make sure that dev is the current device */ + write_lock_irqsave(&port->cad_lock, flags); if (port->cad != dev) { + write_unlock_irqrestore (&port->cad_lock, flags); printk(KERN_WARNING "%s: %s tried to release parport " "when not owner\n", port->name, dev->name); return; @@ -846,7 +854,6 @@ } #endif - write_lock_irqsave(&port->cad_lock, flags); port->cad = NULL; write_unlock_irqrestore(&port->cad_lock, flags); @@ -863,7 +870,7 @@ return; } else if (pd->wakeup) { pd->wakeup(pd->private); - if (dev->port->cad) + if (dev->port->cad) /* racy but no matter */ return; } else { printk(KERN_ERR "%s: don't know how to wake %s\n", port->name, pd->name); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids --- v2.3.99-pre8/linux/drivers/pci/pci.ids Thu May 11 15:30:07 2000 +++ linux/drivers/pci/pci.ids Sat May 20 11:32:08 2000 @@ -2268,10 +2268,13 @@ 1164 Advanced Peripherals Technologies 1165 Imagraph Corporation 0001 Motion TPEG Recorder/Player with audio -1166 Relience Computer +1166 ServerWorks 0007 CNB20-LE CPU to PCI Bridge 0008 CNB20HE - 0009 CNB20HE + 0009 CNB20LE + 0010 CIOB30 + 0011 CMIC_HE + 0201 CSB5 1167 Mutoh Industries Inc 1168 Thine Electronics Inc 1169 Centre for Development of Advanced Computing diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c --- v2.3.99-pre8/linux/drivers/pcmcia/yenta.c Thu May 11 15:30:07 2000 +++ linux/drivers/pcmcia/yenta.c Sat May 20 11:28:14 2000 @@ -564,7 +564,7 @@ */ static void yenta_power_sense(pci_socket_t *socket) { - u32 status = config_readl(socket, CB_SOCKET_STATE); + u32 status = cb_readl(socket, CB_SOCKET_STATE); /* * Nothing inserted, nothing to sense.. diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/s390/block/dasd_proc.c linux/drivers/s390/block/dasd_proc.c --- v2.3.99-pre8/linux/drivers/s390/block/dasd_proc.c Fri May 12 14:18:55 2000 +++ linux/drivers/s390/block/dasd_proc.c Sun May 21 20:34:37 2000 @@ -19,64 +19,16 @@ extern int dasd_proc_read_debug ( char *, char **, off_t, int); #endif /* DASD_PROFILE */ -struct proc_dir_entry dasd_proc_root_entry = { - 0, - 4,"dasd", - S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP, - 1,0,0, - 0, - NULL, -}; - -struct proc_dir_entry dasd_proc_devices_entry = { - 0, - 7,"devices", - S_IFREG | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP, - 1,0,0, - 0, - NULL, - &dasd_proc_read_devices, -}; - -#ifdef DASD_PROFILE -struct proc_dir_entry dasd_proc_stats_entry = { - 0, - 10,"statistics", - S_IFREG | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP, - 1,0,0, - 0, - NULL, - &dasd_proc_read_statistics, -}; - -struct proc_dir_entry dasd_proc_debug_entry = { - 0, - 5,"debug", - S_IFREG | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP, - 1,0,0, - 0, - NULL, - &dasd_proc_read_debug, -}; -#endif /* DASD_PROFILE */ - -struct proc_dir_entry dasd_proc_device_template = { - 0, - 6,"dd????", - S_IFBLK | S_IRUGO | S_IWUSR | S_IWGRP, - 1,0,0, - 0, - NULL, -}; +static struct proc_dir_entry *dasd_proc_root_entry; void dasd_proc_init ( void ) { - proc_register( & proc_root, & dasd_proc_root_entry); - proc_register( & dasd_proc_root_entry, & dasd_proc_devices_entry); + dasd_proc_root_entry = proc_mkdir("dasd", NULL); + create_proc_info_entry("devices",0,&dasd_proc_root_entry,dasd_proc_read_devices); #ifdef DASD_PROFILE - proc_register( & dasd_proc_root_entry, & dasd_proc_stats_entry); - proc_register( & dasd_proc_root_entry, & dasd_proc_debug_entry); + create_proc_info_entry("statistics",0,&dasd_proc_root_entry,dasd_proc_read_statistics); + create_proc_info_entry("debug",0,&dasd_proc_root_entry,dasd_proc_read_debug); #endif /* DASD_PROFILE */ } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c --- v2.3.99-pre8/linux/drivers/scsi/BusLogic.c Wed Dec 29 13:13:18 1999 +++ linux/drivers/scsi/BusLogic.c Sun May 21 11:38:47 2000 @@ -4354,7 +4354,8 @@ HostAdapter, Length, BusLogic_MessageBufferSize); if ((Length -= Offset) <= 0) return 0; if (Length >= BytesAvailable) Length = BytesAvailable; - *StartPointer = &HostAdapter->MessageBuffer[Offset]; + memcpy(ProcBuffer, HostAdapter->MessageBuffer + Offset, Length); + *StartPointer = ProcBuffer; return Length; } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c --- v2.3.99-pre8/linux/drivers/scsi/aha152x.c Thu May 11 15:30:07 2000 +++ linux/drivers/scsi/aha152x.c Sun May 21 20:18:08 2000 @@ -13,9 +13,13 @@ * General Public License for more details. * * - * $Id: aha152x.c,v 2.0 1999/12/25 15:07:32 fischer Exp fischer $ + * $Id: aha152x.c,v 2.1 2000/05/17 16:23:17 fischer Exp fischer $ * * $Log: aha152x.c,v $ + * Revision 2.1 2000/05/17 16:23:17 fischer + * - signature update + * - fix for data out w/o scatter gather + * * Revision 2.0 1999/12/25 15:07:32 fischer * - interrupt routine completly reworked * - basic support for new eh code @@ -202,7 +206,7 @@ #include -#ifdef PCMCIA +#if defined(PCMCIA) #undef MODULE #endif @@ -275,7 +279,6 @@ #define DPRINTK(when,msgs...) #define DO_LOCK(flags) spin_lock_irqsave(&QLOCK,flags) #define DO_UNLOCK(flags) spin_unlock_irqrestore(&QLOCK,flags) -#define DEBUG_DEFAULT 0 #endif #define LEAD "(scsi%d:%d:%d) " @@ -290,6 +293,7 @@ (cmd) ? ((cmd)->lun & 0x07) : -1 #define DELAY_DEFAULT 100 +#define DEBUG_DEFAULT 0 /* possible irq range */ #if defined(PCMCIA) @@ -1714,7 +1718,9 @@ */ int aha152x_host_reset(Scsi_Cmnd * SCpnt) { +#if defined(AHA152X_DEBUG) struct Scsi_Host *shpnt = SCpnt->host; +#endif DPRINTK(debug_eh, DEBUG_LEAD "aha152x_host_reset(%p)\n", CMDINFO(SCpnt), SCpnt); @@ -2731,14 +2737,19 @@ CURRENT_SC->resid += data_count; - data_count -= CURRENT_SC->SCp.ptr - CURRENT_SC->SCp.buffer->address; - while(data_count>0) { - CURRENT_SC->SCp.buffer--; - CURRENT_SC->SCp.buffers_residual++; - data_count -= CURRENT_SC->SCp.buffer->length; + if(CURRENT_SC->use_sg) { + data_count -= CURRENT_SC->SCp.ptr - CURRENT_SC->SCp.buffer->address; + while(data_count>0) { + CURRENT_SC->SCp.buffer--; + CURRENT_SC->SCp.buffers_residual++; + data_count -= CURRENT_SC->SCp.buffer->length; + } + CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address - data_count; + CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length + data_count; + } else { + CURRENT_SC->SCp.ptr -= data_count; + CURRENT_SC->SCp.this_residual += data_count; } - CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address - data_count; - CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length + data_count; } DPRINTK(debug_datao, DEBUG_LEAD "datao_end: request_bufflen=%d; resid=%d; stcnt=%d\n", diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c --- v2.3.99-pre8/linux/drivers/scsi/megaraid.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/scsi/megaraid.c Sun May 21 20:18:08 2000 @@ -1481,7 +1481,7 @@ if ((flag & BOARD_QUARTZ) && (skip_id == -1)) { u16 magic; pci_read_config_word(pdev, PCI_CONF_AMISIG, &magic); - if (magic != AMI_SIGNATURE) + if ((magic != AMI_SIGNATURE) && (magic != AMI_SIGNATURE_471)) continue; /* not an AMI board */ } printk (KERN_INFO "megaraid: found 0x%4.04x:0x%4.04x: in %s\n", diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/scsi/megaraid.h linux/drivers/scsi/megaraid.h --- v2.3.99-pre8/linux/drivers/scsi/megaraid.h Fri Jan 28 15:09:08 2000 +++ linux/drivers/scsi/megaraid.h Tue May 23 14:20:38 2000 @@ -109,6 +109,7 @@ #define PCI_CONF_IRQ_OFFSET 0x3c #define PCI_CONF_AMISIG 0xa0 #define AMI_SIGNATURE 0x3344 +#define AMI_SIGNATURE_471 0xCCCC #if LINUX_VERSION_CODE < 0x20100 #define MEGARAID \ diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/ac97_codec.c linux/drivers/sound/ac97_codec.c --- v2.3.99-pre8/linux/drivers/sound/ac97_codec.c Thu May 11 15:30:07 2000 +++ linux/drivers/sound/ac97_codec.c Sun May 21 20:18:08 2000 @@ -71,6 +71,7 @@ {0x83847605, "SigmaTel STAC9704" , NULL}, {0x83847608, "SigmaTel STAC9708" , NULL}, {0x83847609, "SigmaTel STAC9721/23" , sigmatel_init}, + {0x54524106, "TriTech TR28026" , NULL}, {0x54524108, "TriTech TR28028" , NULL}, {0x574D4C00, "Wolfson WM9704" , NULL}, {0x00000000, NULL, NULL} @@ -330,6 +331,10 @@ /* else, write the first set in the mask as the output */ + /* clear out current set value first (AC97 supports only 1 input!) */ + val = (1 << ac97_rm2oss[codec->codec_read(codec, AC97_RECORD_SELECT)&0x07]); + if (mask != val) mask &= ~val; + val = ffs(mask); val = ac97_oss_rm[val-1]; val |= val << 8; /* set both channels */ @@ -418,6 +423,7 @@ switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ if (!codec->recmask_io) return -EINVAL; + if(!val) return 0; if (!(val &= codec->record_sources)) return -EINVAL; codec->recmask_io(codec, 0, val); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c --- v2.3.99-pre8/linux/drivers/sound/cmpci.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/sound/cmpci.c Sun May 21 20:18:08 2000 @@ -586,7 +586,7 @@ /* --------------------------------------------------------------------- */ -#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT) +#define DMABUF_DEFAULTORDER (16-PAGE_SHIFT) #define DMABUF_MINORDER 1 static void dealloc_dmabuf(struct dmabuf *db) diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/dmasound/dmasound_awacs.c linux/drivers/sound/dmasound/dmasound_awacs.c --- v2.3.99-pre8/linux/drivers/sound/dmasound/dmasound_awacs.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/sound/dmasound/dmasound_awacs.c Sat May 20 12:08:24 2000 @@ -18,12 +18,15 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include "awacs_defs.h" #include "dmasound.h" @@ -1577,257 +1580,279 @@ * /dev/mixer abstraction */ -static int PMacMixerIoctl(u_int cmd, u_long arg) +static int awacs_mixer_ioctl(u_int cmd, u_long arg) { int data; - /* Different IOCTLS for burgundy*/ - if (awacs_revision < AWACS_BURGUNDY) { - switch (cmd) { - case SOUND_MIXER_READ_DEVMASK: - data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER - | SOUND_MASK_LINE | SOUND_MASK_MIC - | SOUND_MASK_CD | SOUND_MASK_RECLEV - | SOUND_MASK_ALTPCM - | SOUND_MASK_MONITOR; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECMASK: - data = SOUND_MASK_LINE | SOUND_MASK_MIC - | SOUND_MASK_CD; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECSRC: - data = 0; - if (awacs_reg[0] & MASK_MUX_AUDIN) - data |= SOUND_MASK_LINE; - if (awacs_reg[0] & MASK_MUX_MIC) - data |= SOUND_MASK_MIC; - if (awacs_reg[0] & MASK_MUX_CD) - data |= SOUND_MASK_CD; - if (awacs_reg[1] & MASK_LOOPTHRU) - data |= SOUND_MASK_MONITOR; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_RECSRC: - IOCTL_IN(arg, data); - data &= (SOUND_MASK_LINE - | SOUND_MASK_MIC | SOUND_MASK_CD - | SOUND_MASK_MONITOR); - awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC - | MASK_MUX_AUDIN); - awacs_reg[1] &= ~MASK_LOOPTHRU; - if (data & SOUND_MASK_LINE) - awacs_reg[0] |= MASK_MUX_AUDIN; - if (data & SOUND_MASK_MIC) - awacs_reg[0] |= MASK_MUX_MIC; - if (data & SOUND_MASK_CD) - awacs_reg[0] |= MASK_MUX_CD; - if (data & SOUND_MASK_MONITOR) - awacs_reg[1] |= MASK_LOOPTHRU; - awacs_write(awacs_reg[0] | MASK_ADDR0); - awacs_write(awacs_reg[1] | MASK_ADDR1); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_STEREODEVS: - data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER - | SOUND_MASK_RECLEV; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_CAPS: - return IOCTL_OUT(arg, 0); - case SOUND_MIXER_READ_VOLUME: - data = (awacs_reg[1] & MASK_AMUTE)? 0: - awacs_get_volume(awacs_reg[2], 6); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - return IOCTL_OUT(arg, dmasound_set_volume(data)); - case SOUND_MIXER_READ_SPEAKER: - if (awacs_revision == 3 - && sys_ctrler == SYS_CTRLER_CUDA) - data = awacs_spkr_vol; - else - data = (awacs_reg[1] & MASK_CMUTE)? 0: - awacs_get_volume(awacs_reg[4], 6); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_SPEAKER: - IOCTL_IN(arg, data); - if (awacs_revision == 3 - && sys_ctrler == SYS_CTRLER_CUDA) - awacs_enable_amp(data); - else - data = awacs_volume_setter(data, 4, MASK_CMUTE, 6); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ - IOCTL_IN(arg, data); - beep_volume = data & 0xff; - /* fall through */ - case SOUND_MIXER_READ_ALTPCM: - return IOCTL_OUT(arg, beep_volume); - case SOUND_MIXER_WRITE_LINE: - IOCTL_IN(arg, data); - awacs_reg[0] &= ~MASK_MUX_AUDIN; - if ((data & 0xff) >= 50) - awacs_reg[0] |= MASK_MUX_AUDIN; - awacs_write(MASK_ADDR0 | awacs_reg[0]); - /* fall through */ - case SOUND_MIXER_READ_LINE: - data = (awacs_reg[0] & MASK_MUX_AUDIN)? 100: 0; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_MIC: - IOCTL_IN(arg, data); - data &= 0xff; - awacs_reg[0] &= ~(MASK_MUX_MIC | MASK_GAINLINE); - if (data >= 25) { - awacs_reg[0] |= MASK_MUX_MIC; - if (data >= 75) - awacs_reg[0] |= MASK_GAINLINE; - } - awacs_write(MASK_ADDR0 | awacs_reg[0]); - /* fall through */ - case SOUND_MIXER_READ_MIC: - data = (awacs_reg[0] & MASK_MUX_MIC)? - (awacs_reg[0] & MASK_GAINLINE? 100: 50): 0; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_CD: - IOCTL_IN(arg, data); - awacs_reg[0] &= ~MASK_MUX_CD; - if ((data & 0xff) >= 50) - awacs_reg[0] |= MASK_MUX_CD; - awacs_write(MASK_ADDR0 | awacs_reg[0]); - /* fall through */ - case SOUND_MIXER_READ_CD: - data = (awacs_reg[0] & MASK_MUX_CD)? 100: 0; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_RECLEV: - IOCTL_IN(arg, data); - data = awacs_volume_setter(data, 0, 0, 4); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECLEV: - data = awacs_get_volume(awacs_reg[0], 4); - return IOCTL_OUT(arg, data); - } - } else { - /* We are, we are, we are... Burgundy or better */ - switch(cmd) { - case SOUND_MIXER_READ_DEVMASK: - data = SOUND_MASK_VOLUME | SOUND_MASK_CD | - SOUND_MASK_LINE | SOUND_MASK_MIC | - SOUND_MASK_SPEAKER | SOUND_MASK_ALTPCM; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECMASK: - data = SOUND_MASK_LINE | SOUND_MASK_MIC - | SOUND_MASK_CD; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECSRC: - data = 0; - if (awacs_reg[0] & MASK_MUX_AUDIN) - data |= SOUND_MASK_LINE; - if (awacs_reg[0] & MASK_MUX_MIC) - data |= SOUND_MASK_MIC; - if (awacs_reg[0] & MASK_MUX_CD) - data |= SOUND_MASK_CD; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_RECSRC: - IOCTL_IN(arg, data); - data &= (SOUND_MASK_LINE - | SOUND_MASK_MIC | SOUND_MASK_CD); - awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC - | MASK_MUX_AUDIN); - if (data & SOUND_MASK_LINE) - awacs_reg[0] |= MASK_MUX_AUDIN; - if (data & SOUND_MASK_MIC) - awacs_reg[0] |= MASK_MUX_MIC; - if (data & SOUND_MASK_CD) - awacs_reg[0] |= MASK_MUX_CD; - awacs_write(awacs_reg[0] | MASK_ADDR0); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_STEREODEVS: - data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER - | SOUND_MASK_RECLEV | SOUND_MASK_CD - | SOUND_MASK_LINE; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_CAPS: - return IOCTL_OUT(arg, 0); - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - awacs_burgundy_write_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME, data); - /* Fall through */ - case SOUND_MIXER_READ_VOLUME: - return IOCTL_OUT(arg, awacs_burgundy_read_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME)); - case SOUND_MIXER_WRITE_SPEAKER: - IOCTL_IN(arg, data); - - if (!(data & 0xff)) { - /* Mute the left speaker */ - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x2); - } else { - /* Unmute the left speaker */ - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x2); - } - if (!(data & 0xff00)) { - /* Mute the right speaker */ - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x4); - } else { - /* Unmute the right speaker */ - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, - awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x4); - } - - data = (((data&0xff)*16)/100 > 0xf ? 0xf : - (((data&0xff)*16)/100)) + - ((((data>>8)*16)/100 > 0xf ? 0xf : - ((((data>>8)*16)/100)))<<4); - - awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER, ~data); - /* Fall through */ - case SOUND_MIXER_READ_SPEAKER: - data = awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER); - data = (((data & 0xf)*100)/16) + ((((data>>4)*100)/16)<<8); - return IOCTL_OUT(arg, ~data); - case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ - IOCTL_IN(arg, data); - beep_volume = data & 0xff; - /* fall through */ - case SOUND_MIXER_READ_ALTPCM: - return IOCTL_OUT(arg, beep_volume); - case SOUND_MIXER_WRITE_LINE: - IOCTL_IN(arg, data); - awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLLINE, data); - - /* fall through */ - case SOUND_MIXER_READ_LINE: - data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLLINE); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_MIC: - IOCTL_IN(arg, data); - /* Mic is mono device */ - data = (data << 8) + (data << 24); - awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLMIC, data); - /* fall through */ - case SOUND_MIXER_READ_MIC: - data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLMIC); - data <<= 24; - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_CD: - IOCTL_IN(arg, data); - awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLCD, data); - /* fall through */ - case SOUND_MIXER_READ_CD: - data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLCD); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_WRITE_RECLEV: - IOCTL_IN(arg, data); - data = awacs_volume_setter(data, 0, 0, 4); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_READ_RECLEV: - data = awacs_get_volume(awacs_reg[0], 4); - return IOCTL_OUT(arg, data); - case SOUND_MIXER_OUTMASK: - break; - case SOUND_MIXER_OUTSRC: - break; - } + + switch (cmd) { + case SOUND_MIXER_READ_DEVMASK: + data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER + | SOUND_MASK_LINE | SOUND_MASK_MIC + | SOUND_MASK_CD | SOUND_MASK_RECLEV + | SOUND_MASK_ALTPCM + | SOUND_MASK_MONITOR; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECMASK: + data = SOUND_MASK_LINE | SOUND_MASK_MIC + | SOUND_MASK_CD; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECSRC: + data = 0; + if (awacs_reg[0] & MASK_MUX_AUDIN) + data |= SOUND_MASK_LINE; + if (awacs_reg[0] & MASK_MUX_MIC) + data |= SOUND_MASK_MIC; + if (awacs_reg[0] & MASK_MUX_CD) + data |= SOUND_MASK_CD; + if (awacs_reg[1] & MASK_LOOPTHRU) + data |= SOUND_MASK_MONITOR; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_RECSRC: + IOCTL_IN(arg, data); + data &= (SOUND_MASK_LINE + | SOUND_MASK_MIC | SOUND_MASK_CD + | SOUND_MASK_MONITOR); + awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC + | MASK_MUX_AUDIN); + awacs_reg[1] &= ~MASK_LOOPTHRU; + if (data & SOUND_MASK_LINE) + awacs_reg[0] |= MASK_MUX_AUDIN; + if (data & SOUND_MASK_MIC) + awacs_reg[0] |= MASK_MUX_MIC; + if (data & SOUND_MASK_CD) + awacs_reg[0] |= MASK_MUX_CD; + if (data & SOUND_MASK_MONITOR) + awacs_reg[1] |= MASK_LOOPTHRU; + awacs_write(awacs_reg[0] | MASK_ADDR0); + awacs_write(awacs_reg[1] | MASK_ADDR1); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_STEREODEVS: + data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER + | SOUND_MASK_RECLEV; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_CAPS: + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_READ_VOLUME: + data = (awacs_reg[1] & MASK_AMUTE)? 0: + awacs_get_volume(awacs_reg[2], 6); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_VOLUME: + IOCTL_IN(arg, data); + return IOCTL_OUT(arg, PMacSetVolume(data)); + case SOUND_MIXER_READ_SPEAKER: + if (awacs_revision == 3 + && sys_ctrler == SYS_CTRLER_CUDA) + data = awacs_spkr_vol; + else + data = (awacs_reg[1] & MASK_CMUTE)? 0: + awacs_get_volume(awacs_reg[4], 6); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_SPEAKER: + IOCTL_IN(arg, data); + if (awacs_revision == 3 + && sys_ctrler == SYS_CTRLER_CUDA) + awacs_enable_amp(data); + else + data = awacs_volume_setter(data, 4, MASK_CMUTE, 6); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ + IOCTL_IN(arg, data); + beep_volume = data & 0xff; + /* fall through */ + case SOUND_MIXER_READ_ALTPCM: + return IOCTL_OUT(arg, beep_volume); + case SOUND_MIXER_WRITE_LINE: + IOCTL_IN(arg, data); + awacs_reg[0] &= ~MASK_MUX_AUDIN; + if ((data & 0xff) >= 50) + awacs_reg[0] |= MASK_MUX_AUDIN; + awacs_write(MASK_ADDR0 | awacs_reg[0]); + /* fall through */ + case SOUND_MIXER_READ_LINE: + data = (awacs_reg[0] & MASK_MUX_AUDIN)? 100: 0; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_MIC: + IOCTL_IN(arg, data); + data &= 0xff; + awacs_reg[0] &= ~(MASK_MUX_MIC | MASK_GAINLINE); + if (data >= 25) { + awacs_reg[0] |= MASK_MUX_MIC; + if (data >= 75) + awacs_reg[0] |= MASK_GAINLINE; + } + awacs_write(MASK_ADDR0 | awacs_reg[0]); + /* fall through */ + case SOUND_MIXER_READ_MIC: + data = (awacs_reg[0] & MASK_MUX_MIC)? + (awacs_reg[0] & MASK_GAINLINE? 100: 50): 0; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_CD: + IOCTL_IN(arg, data); + awacs_reg[0] &= ~MASK_MUX_CD; + if ((data & 0xff) >= 50) + awacs_reg[0] |= MASK_MUX_CD; + awacs_write(MASK_ADDR0 | awacs_reg[0]); + /* fall through */ + case SOUND_MIXER_READ_CD: + data = (awacs_reg[0] & MASK_MUX_CD)? 100: 0; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_RECLEV: + IOCTL_IN(arg, data); + data = awacs_volume_setter(data, 0, 0, 4); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECLEV: + data = awacs_get_volume(awacs_reg[0], 4); + return IOCTL_OUT(arg, data); + case MIXER_WRITE(SOUND_MASK_MONITOR): + IOCTL_IN(arg, data); + awacs_reg[1] &= ~MASK_LOOPTHRU; + if ((data & 0xff) >= 50) + awacs_reg[1] |= MASK_LOOPTHRU; + awacs_write(MASK_ADDR1 | awacs_reg[1]); + /* fall through */ + case MIXER_READ(SOUND_MASK_MONITOR): + data = (awacs_reg[1] & MASK_LOOPTHRU)? 100: 0; + return IOCTL_OUT(arg, data); } return -EINVAL; +} + +static int burgundy_mixer_ioctl(u_int cmd, u_long arg) +{ + int data; + + /* We are, we are, we are... Burgundy or better */ + switch(cmd) { + case SOUND_MIXER_READ_DEVMASK: + data = SOUND_MASK_VOLUME | SOUND_MASK_CD | + SOUND_MASK_LINE | SOUND_MASK_MIC | + SOUND_MASK_SPEAKER | SOUND_MASK_ALTPCM; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECMASK: + data = SOUND_MASK_LINE | SOUND_MASK_MIC + | SOUND_MASK_CD; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECSRC: + data = 0; + if (awacs_reg[0] & MASK_MUX_AUDIN) + data |= SOUND_MASK_LINE; + if (awacs_reg[0] & MASK_MUX_MIC) + data |= SOUND_MASK_MIC; + if (awacs_reg[0] & MASK_MUX_CD) + data |= SOUND_MASK_CD; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_RECSRC: + IOCTL_IN(arg, data); + data &= (SOUND_MASK_LINE + | SOUND_MASK_MIC | SOUND_MASK_CD); + awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC + | MASK_MUX_AUDIN); + if (data & SOUND_MASK_LINE) + awacs_reg[0] |= MASK_MUX_AUDIN; + if (data & SOUND_MASK_MIC) + awacs_reg[0] |= MASK_MUX_MIC; + if (data & SOUND_MASK_CD) + awacs_reg[0] |= MASK_MUX_CD; + awacs_write(awacs_reg[0] | MASK_ADDR0); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_STEREODEVS: + data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER + | SOUND_MASK_RECLEV | SOUND_MASK_CD + | SOUND_MASK_LINE; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_CAPS: + return IOCTL_OUT(arg, 0); + case SOUND_MIXER_WRITE_VOLUME: + IOCTL_IN(arg, data); + awacs_burgundy_write_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME, data); + /* Fall through */ + case SOUND_MIXER_READ_VOLUME: + return IOCTL_OUT(arg, awacs_burgundy_read_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME)); + case SOUND_MIXER_WRITE_SPEAKER: + IOCTL_IN(arg, data); + + if (!(data & 0xff)) { + /* Mute the left speaker */ + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, + awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x2); + } else { + /* Unmute the left speaker */ + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, + awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x2); + } + if (!(data & 0xff00)) { + /* Mute the right speaker */ + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, + awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x4); + } else { + /* Unmute the right speaker */ + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES, + awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x4); + } + + data = (((data&0xff)*16)/100 > 0xf ? 0xf : + (((data&0xff)*16)/100)) + + ((((data>>8)*16)/100 > 0xf ? 0xf : + ((((data>>8)*16)/100)))<<4); + + awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER, ~data); + /* Fall through */ + case SOUND_MIXER_READ_SPEAKER: + data = awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER); + data = (((data & 0xf)*100)/16) + ((((data>>4)*100)/16)<<8); + return IOCTL_OUT(arg, ~data); + case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ + IOCTL_IN(arg, data); + beep_volume = data & 0xff; + /* fall through */ + case SOUND_MIXER_READ_ALTPCM: + return IOCTL_OUT(arg, beep_volume); + case SOUND_MIXER_WRITE_LINE: + IOCTL_IN(arg, data); + awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLLINE, data); + + /* fall through */ + case SOUND_MIXER_READ_LINE: + data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLLINE); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_MIC: + IOCTL_IN(arg, data); + /* Mic is mono device */ + data = (data << 8) + (data << 24); + awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLMIC, data); + /* fall through */ + case SOUND_MIXER_READ_MIC: + data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLMIC); + data <<= 24; + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_CD: + IOCTL_IN(arg, data); + awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLCD, data); + /* fall through */ + case SOUND_MIXER_READ_CD: + data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLCD); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_WRITE_RECLEV: + IOCTL_IN(arg, data); + data = awacs_volume_setter(data, 0, 0, 4); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_READ_RECLEV: + data = awacs_get_volume(awacs_reg[0], 4); + return IOCTL_OUT(arg, data); + case SOUND_MIXER_OUTMASK: + break; + case SOUND_MIXER_OUTSRC: + break; + } + return -EINVAL; +} + +static int PMacMixerIoctl(u_int cmd, u_long arg) +{ + /* Different IOCTLS for burgundy*/ + if (awacs_revision >= AWACS_BURGUNDY) + return burgundy_mixer_ioctl(cmd, arg); + return awacs_mixer_ioctl(cmd, arg); } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/emu10k1/main.c linux/drivers/sound/emu10k1/main.c --- v2.3.99-pre8/linux/drivers/sound/emu10k1/main.c Thu May 11 15:30:08 2000 +++ linux/drivers/sound/emu10k1/main.c Sat May 13 08:19:21 2000 @@ -80,7 +80,7 @@ "EMU10K1", }; -static struct pci_device_id emu10k1_pci_tbl[] = { +static struct pci_device_id emu10k1_pci_tbl[] __devinitdata = { {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_EMU10K1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, EMU10K1}, {0,} diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c --- v2.3.99-pre8/linux/drivers/sound/es1370.c Thu May 11 15:30:08 2000 +++ linux/drivers/sound/es1370.c Sat May 13 08:19:21 2000 @@ -2599,7 +2599,7 @@ static struct pci_device_id id_table[] __devinitdata = { { PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, - { 0, 0, 0, 0, 0, 0 } + { 0, } }; MODULE_DEVICE_TABLE(pci, id_table); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c --- v2.3.99-pre8/linux/drivers/sound/es1371.c Thu May 11 15:30:08 2000 +++ linux/drivers/sound/es1371.c Sat May 13 08:19:21 2000 @@ -2804,7 +2804,7 @@ { PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, { PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_CT5880, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, { PCI_VENDOR_ID_ECTIVA, PCI_DEVICE_ID_ECTIVA_EV1938, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, - { 0, 0, 0, 0, 0, 0 } + { 0, } }; MODULE_DEVICE_TABLE(pci, id_table); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c --- v2.3.99-pre8/linux/drivers/sound/esssolo1.c Thu May 11 15:30:08 2000 +++ linux/drivers/sound/esssolo1.c Sat May 13 08:19:21 2000 @@ -2335,7 +2335,7 @@ static struct pci_device_id id_table[] __devinitdata = { { PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, - { 0, 0, 0, 0, 0, 0 } + { 0, } }; MODULE_DEVICE_TABLE(pci, id_table); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c --- v2.3.99-pre8/linux/drivers/sound/sb_card.c Thu May 11 15:30:08 2000 +++ linux/drivers/sound/sb_card.c Sat May 13 08:14:03 2000 @@ -249,6 +249,11 @@ ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0,0,0,0, 0,1,1,-1}, + {"Sound Blaster 16", + ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0025), + ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), + 0,0,0,0, + 0,1,1,-1}, {"Sound Blaster 16", ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0026), ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), @@ -364,6 +369,11 @@ ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0,0,0,0, 0,1,1,-1}, + {"ESS 1688", + ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0968), + ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968), + 0,0,0,0, + 0,1,2,-1}, {"ESS 1868", ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), @@ -442,11 +452,6 @@ ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001), ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 1,0,0,0}, - {"Creative SB16 PnP", - ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002a), - ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), - 0,0,0,0, - 0,1,1,-1}, {0} }; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c --- v2.3.99-pre8/linux/drivers/sound/sonicvibes.c Thu May 11 15:30:08 2000 +++ linux/drivers/sound/sonicvibes.c Sat May 13 08:19:21 2000 @@ -2634,7 +2634,7 @@ static struct pci_device_id id_table[] __devinitdata = { { PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SONICVIBES, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, - { 0, 0, 0, 0, 0, 0 } + { 0, } }; MODULE_DEVICE_TABLE(pci, id_table); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/trident.c linux/drivers/sound/trident.c --- v2.3.99-pre8/linux/drivers/sound/trident.c Thu May 11 15:30:08 2000 +++ linux/drivers/sound/trident.c Sun May 21 20:18:08 2000 @@ -29,6 +29,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * History + * v0.14.3 May 20 2000 Aaron Holtzman + * Fix kfree'd memory access in release + * Fix race in open while looking for a free virtual channel slot + * remove open_wait wq (which appears to be unused) * v0.14.2 Mar 29 2000 Ching Ling Lee * Add clear to silence advance in trident_update_ptr * fix invalid data of the end of the sound @@ -166,10 +170,6 @@ unsigned int magic; struct trident_card *card; /* Card info */ - /* single open lock mechanism, only used for recording */ - struct semaphore open_sem; - wait_queue_head_t open_wait; - /* file mode */ mode_t open_mode; @@ -261,6 +261,9 @@ /* We keep trident cards in a linked list */ struct trident_card *next; + /* single open lock mechanism, only used for recording */ + struct semaphore open_sem; + /* The trident has a certain amount of cross channel interaction so we use a single per card lock */ spinlock_t lock; @@ -1904,6 +1907,7 @@ /* find an avaiable virtual channel (instance of /dev/dsp) */ while (card != NULL) { + down(&card->open_sem); for (i = 0; i < NR_HW_CH; i++) { if (card->states[i] == NULL) { state = card->states[i] = (struct trident_state *) @@ -1915,6 +1919,7 @@ goto found_virt; } } + up(&card->open_sem); card = card->next; } /* no more virtual channel avaiable */ @@ -1939,10 +1944,8 @@ state->card = card; state->magic = TRIDENT_STATE_MAGIC; init_waitqueue_head(&dmabuf->wait); - init_MUTEX(&state->open_sem); file->private_data = state; - down(&state->open_sem); /* set default sample format. According to OSS Programmer's Guide /dev/dsp should be default to unsigned 8-bits, mono, with sample rate 8kHz and @@ -1985,7 +1988,7 @@ } state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); - up(&state->open_sem); + up(&card->open_sem); #ifdef DEBUG printk(KERN_ERR "trident: open virtual channel %d, hard channel %d\n", @@ -1999,6 +2002,7 @@ static int trident_release(struct inode *inode, struct file *file) { struct trident_state *state = (struct trident_state *)file->private_data; + struct trident_card *card = state->card; struct dmabuf *dmabuf = &state->dmabuf; VALIDATE_STATE(state); @@ -2009,25 +2013,25 @@ } /* stop DMA state machine and free DMA buffers/channels */ - down(&state->open_sem); + down(&card->open_sem); if (file->f_mode & FMODE_WRITE) { stop_dac(state); dealloc_dmabuf(state); state->card->free_pcm_channel(state->card, dmabuf->channel->num); } + if (file->f_mode & FMODE_READ) { stop_adc(state); dealloc_dmabuf(state); state->card->free_pcm_channel(state->card, dmabuf->channel->num); } - kfree(state->card->states[state->virt]); - state->card->states[state->virt] = NULL; - state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); + card->states[state->virt] = NULL; + kfree(state); /* we're covered by the open_sem */ - up(&state->open_sem); + up(&card->open_sem); MOD_DEC_USE_COUNT; return 0; @@ -2408,6 +2412,7 @@ card->banks[BANK_A].bitmap = 0UL; card->banks[BANK_B].addresses = &bank_b_addrs; card->banks[BANK_B].bitmap = 0UL; + init_MUTEX(&card->open_sem); spin_lock_init(&card->lock); devs = card; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c --- v2.3.99-pre8/linux/drivers/sound/via82cxxx_audio.c Fri May 12 14:18:55 2000 +++ linux/drivers/sound/via82cxxx_audio.c Mon May 15 12:13:10 2000 @@ -305,7 +305,7 @@ static struct pci_device_id via_pci_tbl[] __initdata = { { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0, }, + { 0, } }; MODULE_DEVICE_TABLE(pci,via_pci_tbl); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/tc/tc.c linux/drivers/tc/tc.c --- v2.3.99-pre8/linux/drivers/tc/tc.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/tc/tc.c Sat May 13 08:31:25 2000 @@ -1,4 +1,4 @@ -/* $Id: $ +/* $Id: tc.c,v 1.3 1999/10/09 00:01:32 ralf Exp $ * tc-init: We assume the TURBOchannel to be up and running so * just probe for Modules and fill in the global data structure * tc_bus. @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -231,6 +232,6 @@ tc_bus[i].name, tc_bus[i].firmware); } #endif + ioport_resource.end = KSEG2 - 1; } - } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/tc/tcsyms.c linux/drivers/tc/tcsyms.c --- v2.3.99-pre8/linux/drivers/tc/tcsyms.c Wed Jun 30 11:24:55 1999 +++ linux/drivers/tc/tcsyms.c Sat May 13 08:31:25 2000 @@ -1,13 +1,14 @@ /* - * Turbo Channel Services -- Exported Symbols + * TURBOchannel Services -- Exported Symbols * */ #include #include -EXPORT_SYMBOL(get_tc_irq_nr); -EXPORT_SYMBOL(claim_tc_card); EXPORT_SYMBOL(search_tc_card); -EXPORT_SYMBOL(get_tc_speed); +EXPORT_SYMBOL(claim_tc_card); +EXPORT_SYMBOL(release_tc_card); EXPORT_SYMBOL(get_tc_base_addr); +EXPORT_SYMBOL(get_tc_irq_nr); +EXPORT_SYMBOL(get_tc_speed); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/tc/zs.c linux/drivers/tc/zs.c --- v2.3.99-pre8/linux/drivers/tc/zs.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/tc/zs.c Sat May 13 08:31:25 2000 @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -155,7 +156,7 @@ * memory if large numbers of serial ports are open. */ static unsigned char tmp_buf[4096]; /* This is cheating */ -static struct semaphore tmp_buf_sem = MUTEX; +static DECLARE_MUTEX(tmp_buf_sem); static inline int serial_paranoia_check(struct dec_serial *info, dev_t device, const char *routine) @@ -195,7 +196,7 @@ if (reg != 0) { *channel->control = reg & 0xf; - RECOVERY_DELAY; + wbflush(); RECOVERY_DELAY; } retval = *channel->control; RECOVERY_DELAY; @@ -207,10 +208,10 @@ { if (reg != 0) { *channel->control = reg & 0xf; - RECOVERY_DELAY; + wbflush(); RECOVERY_DELAY; } *channel->control = value; - RECOVERY_DELAY; + wbflush(); RECOVERY_DELAY; return; } @@ -227,7 +228,7 @@ unsigned char value) { *channel->data = value; - RECOVERY_DELAY; + wbflush(); RECOVERY_DELAY; return; } @@ -1313,7 +1314,7 @@ char_time = 1; if (timeout) char_time = MIN(char_time, timeout); - while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) { + while ((read_zsreg(info->zs_channel, 1) & Tx_BUF_EMP) == 0) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(char_time); if (signal_pending(current)) @@ -1351,7 +1352,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, struct dec_serial *info) { - struct wait_queue wait = { current, NULL }; + DECLARE_WAITQUEUE(wait, current); int retval; int do_clocal = 0; @@ -1773,8 +1774,8 @@ info->tqueue.data = info; info->callout_termios =callout_driver.init_termios; info->normal_termios = serial_driver.init_termios; - info->open_wait = 0; - info->close_wait = 0; + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); printk("tty%02d at 0x%08x (irq = %d)", info->line, info->port, info->irq); printk(" is a Z85C30 SCC\n"); @@ -1828,7 +1829,7 @@ while (!(*(info->zs_channel->control) & Tx_BUF_EMP) && --loops) RECOVERY_DELAY; *(info->zs_channel->data) = ch; - RECOVERY_DELAY; + wbflush(); RECOVERY_DELAY; restore_flags(flags); } @@ -2021,10 +2022,9 @@ /* * Register console. */ -long __init zs_serial_console_init(long kmem_start, long kmem_end) +void __init zs_serial_console_init(void) { register_console(&sercons); - return kmem_start; } #endif /* ifdef CONFIG_SERIAL_CONSOLE */ diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/tc/zs.h linux/drivers/tc/zs.h --- v2.3.99-pre8/linux/drivers/tc/zs.h Fri Jun 25 17:38:40 1999 +++ linux/drivers/tc/zs.h Sat May 13 08:31:25 2000 @@ -142,8 +142,8 @@ struct tq_struct tqueue_hangup; struct termios normal_termios; struct termios callout_termios; - struct wait_queue *open_wait; - struct wait_queue *close_wait; + wait_queue_head_t open_wait; + wait_queue_head_t close_wait; }; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/Config.in linux/drivers/usb/Config.in --- v2.3.99-pre8/linux/drivers/usb/Config.in Fri May 12 14:18:55 2000 +++ linux/drivers/usb/Config.in Sat May 20 09:21:51 2000 @@ -43,7 +43,7 @@ dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB - dep_tristate ' USB Mass Storage support (EXPERIMENTAL)' CONFIG_USB_STORAGE $CONFIG_USB + dep_tristate ' USB Mass Storage support (EXPERIMENTAL)' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI if [ "$CONFIG_USB_STORAGE" != "n" ]; then bool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG fi diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/audio.c linux/drivers/usb/audio.c --- v2.3.99-pre8/linux/drivers/usb/audio.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/audio.c Mon May 15 11:38:19 2000 @@ -3,7 +3,7 @@ /* * audio.c -- USB Audio Class driver * - * Copyright (C) 1999 + * Copyright (C) 1999, 2000 * Alan Cox (alan@lxorguk.ukuu.org.uk) * Thomas Sailer (sailer@ife.ee.ethz.ch) * @@ -59,6 +59,21 @@ * 1999-12-20: Fix bad bug in conversion to per interface probing. * disconnect was called multiple times for the audio device, * leading to a premature freeing of the audio structures + * 2000-05-13: I don't remember who changed the find_format routine, + * but the change was completely broken for the Dallas + * chip. Anyway taking sampling rate into account in find_format + * is bad and should not be done unless there are devices with + * completely broken audio descriptors. Unless someone shows + * me such a descriptor, I will not allow find_format to + * take the sampling rate into account. + * Also, the former find_format made: + * - mpg123 play mono instead of stereo + * - sox completely fail for wav's with sample rates < 44.1kHz + * for the Dallas chip. + * Also fix a rather long standing problem with applications that + * use "small" writes producing no sound at all. + * 2000-05-15: My fears came true, the Philips camera indeed has pretty stupid + * audio descriptors. * */ @@ -441,9 +456,9 @@ db->bufsize = nr << PAGE_SHIFT; db->ready = 1; printk(KERN_DEBUG "dmabuf_init: bytepersec %d bufs %d ossfragshift %d ossmaxfrags %d " - "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d\n", + "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d fmt 0x%x\n", bytepersec, bufs, db->ossfragshift, db->ossmaxfrags, db->fragshift, db->fragsize, - db->numfrag, db->dmasize, db->bufsize); + db->numfrag, db->dmasize, db->bufsize, db->format); return 0; } @@ -973,6 +988,8 @@ } spin_lock_irqsave(&as->lock, flags); } + if (u->dma.count <= 0 && !u->dma.mapped) + return 0; u->flags |= FLG_RUNNING; if (!(u->flags & FLG_URB0RUNNING)) { urb = &u->durb[0].urb; @@ -1332,6 +1349,8 @@ } spin_lock_irqsave(&as->lock, flags); } + if (u->dma.count <= 0 && !u->dma.mapped) + return 0; u->flags |= FLG_RUNNING; if (!(u->flags & FLG_URB0RUNNING)) { urb = &u->durb[0].urb; @@ -1395,30 +1414,39 @@ /* --------------------------------------------------------------------- */ -static unsigned int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt, unsigned int rate) +static unsigned int format_goodness(struct audioformat *afp, unsigned int fmt, unsigned int srate) { - unsigned int i; + unsigned int g = 0; + + if (srate < afp->sratelo) + g += afp->sratelo - srate; + if (srate > afp->sratehi) + g += srate - afp->sratehi; + if (AFMT_ISSTEREO(afp->format) && !AFMT_ISSTEREO(fmt)) + g += 0x100000; + if (!AFMT_ISSTEREO(afp->format) && AFMT_ISSTEREO(fmt)) + g += 0x400000; + if (AFMT_IS16BIT(afp->format) && !AFMT_IS16BIT(fmt)) + g += 0x100000; + if (!AFMT_IS16BIT(afp->format) && AFMT_IS16BIT(fmt)) + g += 0x400000; + return g; +} + +static int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt, unsigned int srate) +{ + unsigned int i, g, gb = ~0; + int j = -1; /* default to failure */ - /* first find an exact match, taking both format and sample rate into account, - but ignore stereo bit */ + /* find "best" format (according to format_goodness) */ for (i = 0; i < nr; i++) { - if (afp[i].format == (fmt & ~AFMT_STEREO) && rate >= afp[i].sratelo && rate <= afp[i].sratehi) - return i; + g = format_goodness(&afp[i], fmt, srate); + if (g >= gb) + continue; + j = i; + gb = g; } - - /* second find a match with the same stereo/mono and 8bit/16bit property */ - for (i = 0; i < nr; i++) - if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt) && - !AFMT_IS16BIT(afp[i].format) == !AFMT_IS16BIT(fmt) && - rate >= afp[i].sratelo && rate <= afp[i].sratehi) - return i; - /* third find a match with the same number of channels */ - for (i = 0; i < nr; i++) - if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt) && - rate >= afp[i].sratelo && rate <= afp[i].sratehi) - return i; - /* return failure */ - return -1; + return j; } static int set_format_in(struct usb_audiodev *as) @@ -1430,9 +1458,9 @@ struct usbin *u = &as->usbin; struct dmabuf *d = &u->dma; struct audioformat *fmt; - unsigned int fmtnr, ep; + unsigned int ep; unsigned char data[3]; - int ret; + int fmtnr, ret; if (u->interface < 0 || u->interface >= config->bNumInterfaces) return 0; @@ -1465,7 +1493,9 @@ d->srate = fmt->sratelo; if (d->srate > fmt->sratehi) d->srate = fmt->sratehi; -printk(KERN_DEBUG "usb_audio: set_format_in: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting); +#if 1 + printk(KERN_DEBUG "usb_audio: set_format_in: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting); +#endif if (usb_set_interface(dev, alts->bInterfaceNumber, fmt->altsetting) < 0) { printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n", dev->devnum, u->interface, fmt->altsetting); @@ -1517,9 +1547,9 @@ struct usbout *u = &as->usbout; struct dmabuf *d = &u->dma; struct audioformat *fmt; - unsigned int fmtnr, ep; + unsigned int ep; unsigned char data[3]; - int ret; + int fmtnr, ret; if (u->interface < 0 || u->interface >= config->bNumInterfaces) return 0; @@ -1559,7 +1589,9 @@ d->srate = fmt->sratelo; if (d->srate > fmt->sratehi) d->srate = fmt->sratehi; -printk(KERN_DEBUG "usb_audio: set_format_out: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting); +#if 1 + printk(KERN_DEBUG "usb_audio: set_format_out: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting); +#endif if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) { printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n", dev->devnum, u->interface, fmt->altsetting); @@ -1927,6 +1959,7 @@ if (as->usbout.dma.mapped || !as->usbout.dma.ready) return 0; + usbout_start(as); add_wait_queue(&as->usbout.dma.wait, &wait); for (;;) { __set_current_state(TASK_INTERRUPTIBLE); @@ -2033,6 +2066,7 @@ ssize_t ret = 0; unsigned long flags; unsigned int ptr; + unsigned int start_thr; int cnt, err; if (ppos != &file->f_pos) @@ -2043,10 +2077,11 @@ return ret; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; + start_thr = (as->usbout.dma.srate << AFMT_BYTESSHIFT(as->usbout.dma.format)) / (1000 / (3 * DESCFRAMES)); add_wait_queue(&as->usbout.dma.wait, &wait); while (count > 0) { #if 0 - printk(KERN_DEBUG "usb_audio_write: count %u dma: count %u rdptr %u wrptr %u dmasize %u fragsize %u flags 0x%02x taskst 0x%x\n", + printk(KERN_DEBUG "usb_audio_write: count %u dma: count %u rdptr %u wrptr %u dmasize %u fragsize %u flags 0x%02x taskst 0x%lx\n", count, as->usbout.dma.count, as->usbout.dma.rdptr, as->usbout.dma.wrptr, as->usbout.dma.dmasize, as->usbout.dma.fragsize, as->usbout.flags, current->state); #endif @@ -2097,7 +2132,7 @@ count -= cnt; buffer += cnt; ret += cnt; - if (usbout_start(as)) { + if (as->usbout.dma.count >= start_thr && usbout_start(as)) { if (!ret) ret = -ENODEV; break; @@ -2525,17 +2560,6 @@ /* --------------------------------------------------------------------- */ -/* - * TO DO in order to get to the point of building an OSS interface - * structure, let alone playing music.. - * - * Use kmalloc/kfree for the descriptors we build - * Write the descriptor->OSS convertor code - * Figure how we deal with mixers - * Check alternate configurations. For now assume we will find one - * zero bandwidth (idle) config and one or more live one pers interface. - */ - static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum); static void usb_audio_disconnect(struct usb_device *dev, void *ptr); @@ -2543,25 +2567,11 @@ "audio", usb_audio_probe, usb_audio_disconnect, - /*{ NULL, NULL }, */ LIST_HEAD_INIT(usb_audio_driver.driver_list), + LIST_HEAD_INIT(usb_audio_driver.driver_list), NULL, 0 }; - -#if 0 -static int usb_audio_irq(int state, void *buffer, int len, void *dev_id) -{ -#if 0 - struct usb_audio_device *aud = (struct usb_audio_device *)dev_id; - - printk(KERN_DEBUG "irq on %p\n", aud); -#endif - - return 1; -} -#endif - static void *find_descriptor(void *descstart, unsigned int desclen, void *after, u8 dtype, int iface, int altsetting) { @@ -3559,11 +3569,6 @@ unregister_sound_mixer(ms->dev_mixer); ms->dev_mixer = -1; } -#if 0 - if(aud->irq_handle) - usb_release_irq(dev, aud->irq_handle, aud->irqpipe); - aud->irq_handle = NULL; -#endif release(s); wake_up(&open_wait); } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/hub.c linux/drivers/usb/hub.c --- v2.3.99-pre8/linux/drivers/usb/hub.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/hub.c Sat May 20 11:23:54 2000 @@ -338,7 +338,7 @@ portstatus = le16_to_cpu(portsts.wPortStatus); portchange = le16_to_cpu(portsts.wPortChange); dbg("portstatus %x, change %x, %s", portstatus, portchange, - portstatus&(1<handle; struct input_dev **devptr = &input_dev; + struct input_handle *dnext; /* * Kill any pending repeat timers. @@ -256,9 +257,10 @@ */ while (handle) { + dnext = handle->dnext; input_unlink_handle(handle); handle->handler->disconnect(handle); - handle = handle->dnext; + handle = dnext; } /* @@ -309,15 +311,17 @@ { struct input_handler **handlerptr = &input_handler; struct input_handle *handle = handler->handle; + struct input_handle *hnext; /* * Tell the handler to disconnect from all devices it keeps open. */ while (handle) { + hnext = handle->hnext; input_unlink_handle(handle); handler->disconnect(handle); - handle = handle->hnext; + handle = hnext; } /* diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/ov511.c linux/drivers/usb/ov511.c --- v2.3.99-pre8/linux/drivers/usb/ov511.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/ov511.c Sat May 20 10:37:04 2000 @@ -6,7 +6,7 @@ * Color fixes by by Orion Sky Lawlor, olawlor@acm.org, 2/26/2000 * Snapshot code by Kevin Moore * OV7620 fixes by Charl P. Botha - * Changes by Claudio Matsuoka, claudio@conectiva.com, 3/26/2000 + * Changes by Claudio Matsuoka * * Based on the Linux CPiA driver written by Peter Pregler, * Scott J. Bertin and Johannes Erdfelt. @@ -30,7 +30,7 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static const char version[] = "1.13"; +static const char version[] = "1.14"; #define __NO_VERSION__ @@ -64,6 +64,9 @@ #define DEFAULT_WIDTH 640 #define DEFAULT_HEIGHT 480 +#define GET_SEGSIZE(p) ((p) == VIDEO_PALETTE_RGB24 ? 384 : 256) +#define GET_DEPTH(p) ((p) == VIDEO_PALETTE_RGB24 ? 24 : 8) + /* PARAMETER VARIABLES: */ static int autoadjust = 1; /* CCD dynamically changes exposure, etc... */ @@ -90,9 +93,13 @@ static int i2c_detect_tries = 5; /* For legal values, see the OV7610/7620 specs under register Common F, - upper nybble (set to 0-F) */ + * upper nybble (set to 0-F) */ static int aperture = -1; +/* Force image to be read in RGB instead of BGR. This option allow + * programs that expect RGB data (e.g. gqcam) to work with this driver. */ +static int force_rgb = 0; + MODULE_PARM(autoadjust, "i"); MODULE_PARM(debug, "i"); MODULE_PARM(fix_rgb_offset, "i"); @@ -100,8 +107,9 @@ MODULE_PARM(sensor, "i"); MODULE_PARM(i2c_detect_tries, "i"); MODULE_PARM(aperture, "i"); +MODULE_PARM(force_rgb, "i"); -MODULE_AUTHOR("Mark McClelland (and others)"); +MODULE_AUTHOR("Mark McClelland & Bret Wallach & Orion Sky Lawlor & Kevin Moore & Charl P. Botha & Claudio Matsuoka "); MODULE_DESCRIPTION("OV511 USB Camera Driver"); char kernel_version[] = UTS_RELEASE; @@ -126,6 +134,26 @@ { -1, NULL } }; +static struct palette_list plist[] = { + { VIDEO_PALETTE_GREY, "GREY" }, + { VIDEO_PALETTE_HI240, "HI240" }, + { VIDEO_PALETTE_RGB565, "RGB565" }, + { VIDEO_PALETTE_RGB24, "RGB24" }, + { VIDEO_PALETTE_RGB32, "RGB32" }, + { VIDEO_PALETTE_RGB555, "RGB555" }, + { VIDEO_PALETTE_YUV422, "YUV422" }, + { VIDEO_PALETTE_YUYV, "YUYV" }, + { VIDEO_PALETTE_UYVY, "UYVY" }, + { VIDEO_PALETTE_YUV420, "YUV420" }, + { VIDEO_PALETTE_YUV411, "YUV411" }, + { VIDEO_PALETTE_RAW, "RAW" }, + { VIDEO_PALETTE_YUV422P,"YUV422P" }, + { VIDEO_PALETTE_YUV411P,"YUV411P" }, + { VIDEO_PALETTE_YUV420P,"YUV420P" }, + { VIDEO_PALETTE_YUV410P,"YUV410P" }, + { -1, NULL } +}; + /********************************************************************** * * Memory management @@ -236,7 +264,8 @@ **********************************************************************/ #ifdef CONFIG_PROC_FS -static struct proc_dir_entry *ov511_proc_root = NULL; +static struct proc_dir_entry *ov511_proc_entry = NULL; +static struct proc_dir_entry *video_proc_entry = NULL; #define YES_NO(x) ((x) ? "yes" : "no") @@ -244,7 +273,7 @@ int count, int *eof, void *data) { char *out = page; - int i, len; + int i, j, len; struct usb_ov511 *ov511 = data; /* IMPORTANT: This output MUST be kept under PAGE_SIZE @@ -259,6 +288,10 @@ out += sprintf (out, "subcapture : %s\n", YES_NO (ov511->sub_flag)); out += sprintf (out, "sub_size : %d %d %d %d\n", ov511->subx, ov511->suby, ov511->subw, ov511->subh); + out += sprintf (out, "data_format : %s\n", force_rgb ? "RGB" : "BGR"); + out += sprintf (out, "brightness : %d\n", ov511->brightness >> 8); + out += sprintf (out, "colour : %d\n", ov511->colour >> 8); + out += sprintf (out, "contrast : %d\n", ov511->contrast >> 8); out += sprintf (out, "num_frames : %d\n", OV511_NUMFRAMES); for (i = 0; i < OV511_NUMFRAMES; i++) { out += sprintf (out, "frame : %d\n", i); @@ -266,27 +299,40 @@ ov511->frame[i].depth); out += sprintf (out, " size : %d %d\n", ov511->frame[i].width, ov511->frame[i].height); +#if 0 out += sprintf (out, " hdr_size : %d %d\n", ov511->frame[i].hdrwidth, ov511->frame[i].hdrheight); - out += sprintf (out, " format : %d\n", - ov511->frame[i].format); +#endif + out += sprintf (out, " format : "); + for (j = 0; plist[j].num >= 0; j++) { + if (plist[j].num == ov511->frame[i].format) { + out += sprintf (out, "%s\n", plist[j].name); + break; + } + } + if (plist[j].num < 0) + out += sprintf (out, "unknown\n"); out += sprintf (out, " segsize : %d\n", ov511->frame[i].segsize); + out += sprintf (out, " data_buffer : 0x%p\n", + ov511->frame[i].data); #if 0 - out += sprintf (out, " curline : %d\n", - ov511->frame[i].curline); - out += sprintf (out, " segment : %d\n", - ov511->frame[i].segment); - out += sprintf (out, " scanlength : %ld\n", - ov511->frame[i].scanlength); out += sprintf (out, " bytesread : %ld\n", ov511->frame[i].bytes_read); #endif } out += sprintf (out, "snap_enabled : %s\n", YES_NO (ov511->snap_enabled)); - out += sprintf (out, "bridge : %d\n", ov511->bridge); - out += sprintf (out, "sensor : %d\n", ov511->sensor); + out += sprintf (out, "bridge : %s\n", + ov511->bridge == BRG_OV511 ? "OV511" : + ov511->bridge == BRG_OV511PLUS ? "OV511+" : + "unknown"); + out += sprintf (out, "sensor : %s\n", + ov511->sensor == SEN_OV7610 ? "OV7610" : + ov511->sensor == SEN_OV7620 ? "OV7620" : + ov511->sensor == SEN_OV7620AE ? "OV7620AE" : + "unknown"); out += sprintf (out, "packet_size : %d\n", ov511->packet_size); + out += sprintf (out, "framebuffer : 0x%p\n", ov511->fbuf); len = out - page; len -= off; @@ -303,130 +349,7 @@ static int ov511_write_proc(struct file *file, const char *buffer, unsigned long count, void *data) { - int retval = -EINVAL; - -#if 0 - /* struct cam_data *cam = data; */ - struct usb_ov511 new_params; - int size = count; - int find_colon; - unsigned long val; - u32 command_flags = 0; - u8 new_mains; - - if (down_interruptible(&cam->param_lock)) - return -ERESTARTSYS; - - /* - * Skip over leading whitespace - */ - while (count && isspace(*buffer)) { - --count; - ++buffer; - } - - -#define MATCH(x) \ - ({ \ - int _len = strlen(x), _ret, _colon_found; \ - _ret = (_len <= count && strncmp(buffer, x, _len) == 0); \ - if (_ret) { \ - buffer += _len; \ - count -= _len; \ - if (find_colon) { \ - _colon_found = 0; \ - while (count && (*buffer == ' ' || *buffer == '\t' || \ - (!_colon_found && *buffer == ':'))) { \ - if (*buffer == ':') \ - _colon_found = 1; \ - --count; \ - ++buffer; \ - } \ - if (!count || !_colon_found) \ - retval = -EINVAL; \ - find_colon = 0; \ - } \ - } \ - _ret; \ - }) - -#define VALUE \ - ({ \ - char *_p; \ - unsigned long int _ret; \ - _ret = simple_strtoul(buffer, &_p, 0); \ - if (_p == buffer) \ - retval = -EINVAL; \ - else { \ - count -= _p - buffer; \ - buffer = _p; \ - } \ - _ret; \ - }) - - - retval = 0; - while (count && !retval) { - find_colon = 1; - - if (MATCH("")) { - if (!retval) - val = VALUE; - - if (!retval) { - if (val <= 0xff) - /* ... = val */ ; - else - retval = -EINVAL; - } - } else { - DBG("No match found\n"); - retval = -EINVAL; - } - - if (!retval) { - while (count && isspace(*buffer) && *buffer != '\n') { - --count; - ++buffer; - } - if (count) { - if (*buffer != '\n' && *buffer != ';') - retval = -EINVAL; - else { - --count; - ++buffer; - } - } - } - } - -#undef MATCH -#undef FIRMWARE_VERSION -#undef VALUE -#undef FIND_VALUE -#undef FIND_END - if (!retval) { - if (command_flags & COMMAND_SETCOLOURPARAMS) { - /* Adjust cam->vp to reflect these changes */ - cam->vp.brightness = - new_params.colourParams.brightness*65535/100; - cam->vp.contrast = - new_params.colourParams.contrast*65535/100; - cam->vp.colour = - new_params.colourParams.saturation*65535/100; - } - - memcpy(&cam->params, &new_params, sizeof(struct cam_params)); - cam->mainsFreq = new_mains; - cam->cmd_queue |= command_flags; - retval = size; - } else - PDEBUG(3, "error: %d\n", retval); - - up(&cam->param_lock); -#endif - - return retval; + return -EINVAL; } static void create_proc_ov511_cam (struct usb_ov511 *ov511) @@ -434,14 +357,15 @@ char name[7]; struct proc_dir_entry *ent; - PDEBUG (4, "***************"); - if (!ov511_proc_root || !ov511) + PDEBUG (4, "creating /proc/video/ov511/videoX entry"); + if (!ov511_proc_entry || !ov511) return; sprintf(name, "video%d", ov511->vdev.minor); - PDEBUG (4, "==== name: %s", name); + PDEBUG (4, "creating %s", name); - ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, ov511_proc_root); + ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, ov511_proc_entry); + if (!ent) return; @@ -460,26 +384,44 @@ return; sprintf(name, "video%d", ov511->vdev.minor); - PDEBUG (4, "==== name: %s", name); -#if 0 - remove_proc_entry(name, ov511_proc_root); + PDEBUG (4, "destroying %s", name); + remove_proc_entry(name, ov511_proc_entry); ov511->proc_entry = NULL; -#endif } static void proc_ov511_create(void) { - ov511_proc_root = create_proc_entry("ov511", S_IFDIR, 0); + struct proc_dir_entry *p = NULL; + + /* No current standard here. Alan prefers /proc/video/ as it keeps + * /proc "less cluttered than /proc/randomcardifoundintheshed/" + * -claudio + */ + PDEBUG (3, "creating /proc/video"); + video_proc_entry = proc_mkdir("video", p); + if (!video_proc_entry) { + if (!p) { + err("Unable to initialise /proc/video\n"); + return; + } else { /* FIXME - this doesn't work */ + PDEBUG (3, "/proc/video already exists"); + video_proc_entry = p; + } + } - if (ov511_proc_root) - ov511_proc_root->owner = THIS_MODULE; + ov511_proc_entry = create_proc_entry("ov511", S_IFDIR, video_proc_entry); + + if (ov511_proc_entry) + ov511_proc_entry->owner = THIS_MODULE; else - printk("Unable to initialise /proc/ov511\n"); /***********/ + err("Unable to initialise /proc/video/ov511\n"); } static void proc_ov511_destroy(void) { - remove_proc_entry("ov511", 0); + PDEBUG (3, "removing /proc/video/ov511"); + remove_proc_entry("ov511", video_proc_entry); + remove_proc_entry("video", NULL); } #endif /* CONFIG_PROC_FS */ @@ -510,7 +452,6 @@ return rc; } - /* returns: negative is error, pos or zero is data */ static int ov511_reg_read(struct usb_device *dev, unsigned char reg) { @@ -533,7 +474,6 @@ } } - static int ov511_i2c_write(struct usb_device *dev, unsigned char reg, unsigned char value) @@ -580,7 +520,6 @@ return rc; } - /* returns: negative is error, pos or zero is data */ static int ov511_i2c_read(struct usb_device *dev, unsigned char reg) { @@ -653,7 +592,6 @@ return rc; } - static int ov511_write_regvals(struct usb_device *dev, struct ov511_regvals * pRegvals) { @@ -682,9 +620,8 @@ return rc; } - -#if 0 -static void ov511_dump_i2c_range( struct usb_device *dev, int reg1, int regn) +#ifdef OV511_DEBUG +static void ov511_dump_i2c_range(struct usb_device *dev, int reg1, int regn) { int i; int rc; @@ -694,15 +631,13 @@ } } - -static void ov511_dump_i2c_regs( struct usb_device *dev) +static void ov511_dump_i2c_regs(struct usb_device *dev) { PDEBUG(3, "I2C REGS"); ov511_dump_i2c_range(dev, 0x00, 0x38); } - -static void ov511_dump_reg_range( struct usb_device *dev, int reg1, int regn) +static void ov511_dump_reg_range(struct usb_device *dev, int reg1, int regn) { int i; int rc; @@ -712,8 +647,8 @@ } } - -static void ov511_dump_regs( struct usb_device *dev) +#if 0 +static void ov511_dump_regs(struct usb_device *dev) { PDEBUG(1, "CAMERA INTERFACE REGS"); ov511_dump_reg_range(dev, 0x10, 0x1f); @@ -736,7 +671,7 @@ } #endif - +#endif static int ov511_reset(struct usb_device *dev, unsigned char reset_type) { @@ -752,24 +687,21 @@ return rc; } - /* Temporarily stops OV511 from functioning. Must do this before changing * registers while the camera is streaming */ static inline int ov511_stop(struct usb_device *dev) { - PDEBUG(4, "ov511_stop()"); + PDEBUG(4, "stopping"); return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x3d)); } - /* Restarts OV511 after ov511_stop() is called */ static inline int ov511_restart(struct usb_device *dev) { - PDEBUG(4, "ov511_restart()"); + PDEBUG(4, "restarting"); return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x00)); } - static int ov511_set_packet_size(struct usb_ov511 *ov511, int size) { int alt, mult; @@ -844,9 +776,16 @@ if (ov511_stop(dev) < 0) return -EIO; + ov511->contrast = p->contrast; + ov511->brightness = p->brightness; + ov511->colour = p->colour; + ov511->hue = p->hue; + ov511->whiteness = p->whiteness; + if ((ret = ov511_i2c_read(dev, OV7610_REG_COM_B)) < 0) return -EIO; #if 0 + /* disable auto adjust mode */ if (ov511_i2c_write(dev, OV7610_REG_COM_B, ret & 0xfe) < 0) return -EIO; #endif @@ -880,7 +819,6 @@ return 0; } - static inline int ov7610_get_picture(struct usb_ov511 *ov511, struct video_picture *p) { @@ -903,12 +841,10 @@ p->hue = 0x8000; p->whiteness = 105 << 8; -#if 0 - p->depth = 3; /* Don't know if this is right */ -#else - p->depth = 24; -#endif - p->palette = VIDEO_PALETTE_RGB24; + + /* Can we get these from frame[0]? -claudio? */ + p->depth = ov511->frame[0].depth; + p->palette = ov511->frame[0].format; if (ov511_restart(dev) < 0) return -EIO; @@ -916,6 +852,22 @@ return 0; } +/* FIXME: add 176x144, 160x140 */ +static struct mode_list mlist[] = { + { 640, 480, VIDEO_PALETTE_GREY, 0x4f, 0x3d, 0x00, 0x00, + 0x4f, 0x3d, 0x00, 0x00, 0x04, 0x03, 0x24, 0x04, 0x9e }, + { 640, 480, VIDEO_PALETTE_RGB24,0x4f, 0x3d, 0x00, 0x00, + 0x4f, 0x3d, 0x00, 0x00, 0x06, 0x03, 0x24, 0x04, 0x9e }, + { 320, 240, VIDEO_PALETTE_GREY, 0x27, 0x1f, 0x00, 0x00, + 0x27, 0x1f, 0x00, 0x00, 0x01, 0x03, 0x04, 0x24, 0x1e }, + { 320, 240, VIDEO_PALETTE_RGB24,0x27, 0x1f, 0x00, 0x00, + 0x27, 0x1f, 0x00, 0x00, 0x01, 0x03, 0x04, 0x24, 0x1e }, + { 352, 288, VIDEO_PALETTE_GREY, 0x2b, 0x25, 0x00, 0x00, + 0x2b, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e }, + { 352, 288, VIDEO_PALETTE_RGB24,0x2b, 0x25, 0x00, 0x00, + 0x2b, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e }, + { 0, 0 } +}; static int ov511_mode_init_regs(struct usb_ov511 *ov511, @@ -925,6 +877,7 @@ struct usb_device *dev = ov511->dev; int hwsbase = 0; int hwebase = 0; + int i; PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d", width, height, mode, sub_flag); @@ -975,6 +928,9 @@ break; } +#if 0 + /* FIXME: subwindow support is currently broken! + */ if (width == 640 && height == 480) { if (sub_flag) { /* horizontal window start */ @@ -1018,41 +974,51 @@ } } - ov511_reg_write(dev, 0x14, 0x00); - ov511_reg_write(dev, 0x15, 0x00); + ov511_reg_write(dev, 0x14, 0x00); /* Pixel divisor */ + ov511_reg_write(dev, 0x15, 0x00); /* Line divisor */ /* FIXME?? Shouldn't below be true only for YUV420? */ - ov511_reg_write(dev, 0x18, 0x03); + ov511_reg_write(dev, 0x18, 0x03); /* YUV420/422, YFIR */ - ov511_i2c_write(dev, 0x12, 0x24); - ov511_i2c_write(dev, 0x14, 0x04); + ov511_i2c_write(dev, 0x12, 0x24); /* Common A */ + ov511_i2c_write(dev, 0x14, 0x04); /* Common C */ /* 7620 doesn't have register 0x35, so play it safe */ if (ov511->sensor != SEN_OV7620) ov511_i2c_write(dev, 0x35, 0x9e); - } else if (width == 320 && height == 240) { - ov511_reg_write(dev, 0x12, 0x27); - ov511_reg_write(dev, 0x13, 0x1f); - ov511_reg_write(dev, 0x14, 0x00); - ov511_reg_write(dev, 0x15, 0x00); - ov511_reg_write(dev, 0x18, 0x03); +#endif + + for (i = 0; mlist[i].width; i++) { + if (width != mlist[i].width || + height != mlist[i].height || + mode != mlist[i].mode) + continue; + + ov511_reg_write(dev, 0x12, mlist[i].pxcnt); + ov511_reg_write(dev, 0x13, mlist[i].lncnt); + ov511_reg_write(dev, 0x14, mlist[i].pxdv); + ov511_reg_write(dev, 0x15, mlist[i].lndv); + ov511_reg_write(dev, 0x18, mlist[i].m420); /* Snapshot additions */ - ov511_reg_write(dev, 0x1a, 0x27); - ov511_reg_write(dev, 0x1b, 0x1f); - ov511_reg_write(dev, 0x1c, 0x00); - ov511_reg_write(dev, 0x1d, 0x00); + ov511_reg_write(dev, 0x1a, mlist[i].s_pxcnt); + ov511_reg_write(dev, 0x1b, mlist[i].s_lncnt); + ov511_reg_write(dev, 0x1c, mlist[i].s_pxdv); + ov511_reg_write(dev, 0x1d, mlist[i].s_lndv); - if (mode == VIDEO_PALETTE_GREY) { - ov511_i2c_write(dev, 0x11, 1); /* check */ - } else { - ov511_i2c_write(dev, 0x11, 1); /* check */ - } + ov511_i2c_write(dev, 0x11, mlist[i].clock); /* check */ - ov511_i2c_write(dev, 0x12, 0x04); - ov511_i2c_write(dev, 0x14, 0x24); - ov511_i2c_write(dev, 0x35, 0x1e); - } else { + ov511_i2c_write(dev, 0x12, mlist[i].common_A); + ov511_i2c_write(dev, 0x14, mlist[i].common_C); + + /* 7620 doesn't have register 0x35, so play it safe */ + if (ov511->sensor != SEN_OV7620) + ov511_i2c_write(dev, 0x35, mlist[i].common_L); + + break; + } + + if (mlist[i].width == 0) { err("Unknown mode (%d, %d): %d", width, height, mode); rc = -EINVAL; } @@ -1060,10 +1026,14 @@ if (ov511_restart(ov511->dev) < 0) return -EIO; +#ifdef OV511_DEBUG + if (debug >= 5) + ov511_dump_i2c_regs(dev); +#endif + return rc; } - /********************************************************************** * * Color correction functions @@ -1093,32 +1063,38 @@ ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v, int rowPixels, unsigned char * rgb) { - const double brightness = 1.0; // 0->black; 1->full scale - const double saturation = 1.0; // 0->greyscale; 1->full color + const double brightness = 1.0; /* 0->black; 1->full scale */ + const double saturation = 1.0; /* 0->greyscale; 1->full color */ const double fixScale = brightness * 256 * 256; const int rvScale = (int)(1.402 * saturation * fixScale); const int guScale = (int)(-0.344136 * saturation * fixScale); const int gvScale = (int)(-0.714136 * saturation * fixScale); const int buScale = (int)(1.772 * saturation * fixScale); const int yScale = (int)(fixScale); + int r, g, b; + + g = guScale * u + gvScale * v; + if (force_rgb) { + r = buScale * u; + b = rvScale * v; + } else { + r = rvScale * v; + b = buScale * u; + } - int r = rvScale * v; - int g = guScale * u + gvScale * v; - int b = buScale * u; yTL *= yScale; yTR *= yScale; yBL *= yScale; yBR *= yScale; - //Write out top two pixels + /* Write out top two pixels */ rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL); rgb[2] = LIMIT(r+yTL); rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR); rgb[5] = LIMIT(r+yTR); - //Skip down to next line to write out bottom two pixels + /* Skip down to next line to write out bottom two pixels */ rgb += 3 * rowPixels; rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL); rgb[2] = LIMIT(r+yBL); rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR); rgb[5] = LIMIT(r+yBR); } - /* * For a 640x480 YUV4:2:0 images, data shows up in 1200 384 byte segments. * The first 64 bytes of each segment are U, the next 64 are V. The U and @@ -1155,13 +1131,13 @@ #undef OV511_DUMPPIX static void -ov511_parse_data_rgb24(unsigned char * pIn0, unsigned char * pOut0, +ov511_parse_data_rgb24(unsigned char *pIn0, unsigned char *pOut0, int iOutY, int iOutUV, int iHalf, int iWidth) { #ifndef OV511_DUMPPIX int k, l, m; - unsigned char * pIn; - unsigned char * pOut, * pOut1; + unsigned char *pIn; + unsigned char *pOut, *pOut1; /* Just copy the Y's if in the first stripe */ if (!iHalf) { @@ -1232,7 +1208,6 @@ pOut += 8 * 3; } } - #else /* Just dump pix data straight out for debug */ int i, j; @@ -1249,7 +1224,6 @@ #endif } - /* * For 640x480 RAW BW images, data shows up in 1200 256 byte segments. * The segments represent 4 squares of 8x8 pixels as follows: @@ -1257,11 +1231,11 @@ * 0 1 ... 7 64 65 ... 71 ... 192 193 ... 199 * 8 9 ... 15 72 73 ... 79 200 201 ... 207 * ... ... ... - * 56 57 ... 63 120 121 127 248 249 ... 255 + * 56 57 ... 63 120 121 ... 127 248 249 ... 255 * */ static void -ov511_parse_data_grey(unsigned char * pIn0, unsigned char * pOut0, +ov511_parse_data_grey(unsigned char *pIn0, unsigned char *pOut0, int iOutY, int iWidth) { int k, l, m; @@ -1276,13 +1250,12 @@ for (m = 0; m < 8; m++) { *pOut1++ = *pIn++; } - pOut1 += iWidth - 8; + pOut1 += iWidth - WDIV; } pOut += 8; } } - /* * fixFrameRGBoffset-- * My camera seems to return the red channel about 1 pixel @@ -1317,7 +1290,6 @@ } } - /********************************************************************** * * OV511 data transfer, IRQ handler @@ -1488,7 +1460,6 @@ return totlen; } - static void ov511_isoc_irq(struct urb *urb) { int len; @@ -1520,7 +1491,6 @@ return; } - static int ov511_init_isoc(struct usb_ov511 *ov511) { urb_t *urb; @@ -1595,7 +1565,6 @@ return 0; } - static void ov511_stop_isoc(struct usb_ov511 *ov511) { if (!ov511->streaming || !ov511->dev) @@ -1622,7 +1591,6 @@ } } - static int ov511_new_frame(struct usb_ov511 *ov511, int framenum) { struct ov511_frame *frame; @@ -1658,25 +1626,17 @@ /* Make sure it's not too big */ if (width > DEFAULT_WIDTH) width = DEFAULT_WIDTH; -#if 0 - width = (width / 8) * 8; /* Multiple of 8 */ -#endif - width &= ~7L; + + width &= ~7L; /* Multiple of 8 */ if (height > DEFAULT_HEIGHT) height = DEFAULT_HEIGHT; -#if 0 - height = (height / 4) * 4; /* Multiple of 4 */ -#endif - width &= ~3L; -// /* We want a fresh frame every 30 we get */ -// ov511->compress = (ov511->compress + 1) % 30; + width &= ~3L; /* Multiple of 4 */ return 0; } - /**************************************************************************** * * V4L API @@ -1687,43 +1647,45 @@ { int err = -EBUSY; struct usb_ov511 *ov511 = (struct usb_ov511 *)dev; + int i; - PDEBUG(4, "ov511_open"); + PDEBUG(4, "opening"); down(&ov511->lock); - if (ov511->user) - goto out_unlock; - ov511->frame[0].grabstate = FRAME_UNUSED; - ov511->frame[1].grabstate = FRAME_UNUSED; + if (ov511->user) { + up(&ov511->lock); + return -EBUSY; + } err = -ENOMEM; /* Allocate memory for the frame buffers */ - ov511->fbuf = rvmalloc(2 * MAX_DATA_SIZE); + ov511->fbuf = rvmalloc(OV511_NUMFRAMES * MAX_DATA_SIZE); if (!ov511->fbuf) - goto open_err_ret; + return err; - ov511->frame[0].data = ov511->fbuf; - ov511->frame[1].data = ov511->fbuf + MAX_DATA_SIZE; ov511->sub_flag = 0; - PDEBUG(4, "frame [0] @ %p", ov511->frame[0].data); - PDEBUG(4, "frame [1] @ %p", ov511->frame[1].data); - - ov511->sbuf[0].data = kmalloc(FRAMES_PER_DESC * MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL); - if (!ov511->sbuf[0].data) - goto open_err_on0; - ov511->sbuf[1].data = kmalloc(FRAMES_PER_DESC * MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL); - if (!ov511->sbuf[1].data) - goto open_err_on1; - - PDEBUG(4, "sbuf[0] @ %p", ov511->sbuf[0].data); - PDEBUG(4, "sbuf[1] @ %p", ov511->sbuf[1].data); + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov511->frame[i].grabstate = FRAME_UNUSED; + ov511->frame[i].data = ov511->fbuf + i * MAX_DATA_SIZE; + PDEBUG(4, "frame [%d] @ %p", i, ov511->frame[0].data); + + ov511->sbuf[i].data = kmalloc(FRAMES_PER_DESC * + MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL); + if (!ov511->sbuf[i].data) { +open_free_ret: + while (--i) kfree(ov511->sbuf[i].data); + rvfree(ov511->fbuf, 2 * MAX_DATA_SIZE); + return err; + } + PDEBUG(4, "sbuf[%d] @ %p", i, ov511->sbuf[i].data); + } err = ov511_init_isoc(ov511); if (err) - goto open_err_on2; + goto open_free_ret; ov511->user++; up(&ov511->lock); @@ -1731,24 +1693,12 @@ MOD_INC_USE_COUNT; return 0; - -open_err_on2: - kfree (ov511->sbuf[1].data); -open_err_on1: - kfree (ov511->sbuf[0].data); -open_err_on0: - rvfree(ov511->fbuf, 2 * MAX_DATA_SIZE); -open_err_ret: - return err; -out_unlock: - up(&ov511->lock); - return err; } - static void ov511_close(struct video_device *dev) { struct usb_ov511 *ov511 = (struct usb_ov511 *)dev; + int i; PDEBUG(4, "ov511_close"); @@ -1759,10 +1709,9 @@ ov511_stop_isoc(ov511); - rvfree(ov511->fbuf, 2 * MAX_DATA_SIZE); - - kfree(ov511->sbuf[1].data); - kfree(ov511->sbuf[0].data); + rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE); + for (i = 0; i < OV511_NUMFRAMES; i++) + kfree(ov511->sbuf[i].data); up(&ov511->lock); @@ -1772,7 +1721,6 @@ } } - static int ov511_init_done(struct video_device *dev) { #ifdef CONFIG_PROC_FS @@ -1782,13 +1730,11 @@ return 0; } - static long ov511_write(struct video_device *dev, const char *buf, unsigned long count, int noblock) { return -EINVAL; } - static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg) { struct usb_ov511 *ov511 = (struct usb_ov511 *)vdev; @@ -2097,7 +2043,6 @@ return 0; } - static long ov511_read(struct video_device *dev, char *buf, unsigned long count, int noblock) { struct usb_ov511 *ov511 = (struct usb_ov511 *)dev; @@ -2138,10 +2083,6 @@ frame = &ov511->frame[frmx]; - /* FIXME */ - frame->segsize = frame->format == VIDEO_PALETTE_RGB24 ? 384 : 256; - frame->depth = frame->format == VIDEO_PALETTE_RGB24 ? 24 : 8; - restart: if (!ov511->dev) return -EIO; @@ -2165,11 +2106,8 @@ /* Repeat until we get a snapshot frame */ - if (!ov511->snap_enabled) { - PDEBUG (4, "snap disabled"); - } else { + if (ov511->snap_enabled) PDEBUG (4, "Waiting snapshot frame"); - } if (ov511->snap_enabled && !frame->snapshot) { frame->bytes_read = 0; if (ov511_new_frame(ov511, frmx)) @@ -2178,13 +2116,11 @@ } /* Clear the snapshot */ - if (ov511->snap_enabled) - PDEBUG (4, "Clear snapshot"); if (ov511->snap_enabled && frame->snapshot) { frame->snapshot = 0; - ov511_reg_write(ov511->dev, 0x52, 0x01); - ov511_reg_write(ov511->dev, 0x52, 0x03); - ov511_reg_write(ov511->dev, 0x52, 0x01); + ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01); + ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x03); + ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01); } PDEBUG(4, "frmx=%d, bytes_read=%ld, scanlength=%ld", frmx, @@ -2212,7 +2148,7 @@ /* Mark it as available to be used again. */ ov511->frame[frmx].grabstate = FRAME_UNUSED; - if (ov511_new_frame(ov511, frmx ? 0 : 1)) + if (ov511_new_frame(ov511, !frmx)) err("ov511_new_frame returned error"); } @@ -2221,7 +2157,6 @@ return count; } - static int ov511_mmap(struct video_device *dev, const char *adr, unsigned long size) { @@ -2229,7 +2164,7 @@ unsigned long start = (unsigned long)adr; unsigned long page, pos; - if (!ov511->dev) + if (ov511->dev == NULL) return -EIO; PDEBUG(4, "mmap: %ld (%lX) bytes", size, size); @@ -2238,8 +2173,7 @@ return -EINVAL; pos = (unsigned long)ov511->fbuf; - while (size > 0) - { + while (size > 0) { page = kvirt_to_pa(pos); if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED)) return -EAGAIN; @@ -2254,7 +2188,6 @@ return 0; } - static struct video_device ov511_template = { name: "OV511 USB Camera", type: VID_TYPE_CAPTURE, @@ -2268,7 +2201,6 @@ initialize: ov511_init_done, }; - /**************************************************************************** * * OV511/OV7610 configuration @@ -2281,68 +2213,70 @@ int i, success; int rc; - static struct ov511_regvals aRegvalsNorm7610[] = - {{OV511_I2C_BUS, 0x10, 0xff}, - {OV511_I2C_BUS, 0x16, 0x06}, - {OV511_I2C_BUS, 0x28, 0x24}, - {OV511_I2C_BUS, 0x2b, 0xac}, - {OV511_I2C_BUS, 0x05, 0x00}, - {OV511_I2C_BUS, 0x06, 0x00}, - {OV511_I2C_BUS, 0x12, 0x00}, - {OV511_I2C_BUS, 0x38, 0x81}, - {OV511_I2C_BUS, 0x28, 0x24}, /* 0c */ - {OV511_I2C_BUS, 0x05, 0x00}, - {OV511_I2C_BUS, 0x0f, 0x05}, - {OV511_I2C_BUS, 0x15, 0x01}, - {OV511_I2C_BUS, 0x20, 0x1c}, - {OV511_I2C_BUS, 0x23, 0x2a}, - {OV511_I2C_BUS, 0x24, 0x10}, - {OV511_I2C_BUS, 0x25, 0x8a}, - {OV511_I2C_BUS, 0x27, 0xc2}, - {OV511_I2C_BUS, 0x29, 0x03}, /* 91 */ - {OV511_I2C_BUS, 0x2a, 0x04}, - {OV511_I2C_BUS, 0x2c, 0xfe}, - {OV511_I2C_BUS, 0x30, 0x71}, - {OV511_I2C_BUS, 0x31, 0x60}, - {OV511_I2C_BUS, 0x32, 0x26}, - {OV511_I2C_BUS, 0x33, 0x20}, - {OV511_I2C_BUS, 0x34, 0x48}, - {OV511_I2C_BUS, 0x12, 0x24}, - {OV511_I2C_BUS, 0x11, 0x01}, - {OV511_I2C_BUS, 0x0c, 0x24}, - {OV511_I2C_BUS, 0x0d, 0x24}, - {OV511_DONE_BUS, 0x0, 0x00}, + static struct ov511_regvals aRegvalsNorm7610[] = { + { OV511_I2C_BUS, 0x10, 0xff }, + { OV511_I2C_BUS, 0x16, 0x06 }, + { OV511_I2C_BUS, 0x28, 0x24 }, + { OV511_I2C_BUS, 0x2b, 0xac }, + { OV511_I2C_BUS, 0x05, 0x00 }, + { OV511_I2C_BUS, 0x06, 0x00 }, + { OV511_I2C_BUS, 0x12, 0x00 }, + { OV511_I2C_BUS, 0x38, 0x81 }, + { OV511_I2C_BUS, 0x28, 0x24 }, /* 0c */ + { OV511_I2C_BUS, 0x05, 0x00 }, + { OV511_I2C_BUS, 0x0f, 0x05 }, + { OV511_I2C_BUS, 0x15, 0x01 }, + { OV511_I2C_BUS, 0x20, 0x1c }, + { OV511_I2C_BUS, 0x23, 0x2a }, + { OV511_I2C_BUS, 0x24, 0x10 }, + { OV511_I2C_BUS, 0x25, 0x8a }, + { OV511_I2C_BUS, 0x27, 0xc2 }, + { OV511_I2C_BUS, 0x29, 0x03 }, /* 91 */ + { OV511_I2C_BUS, 0x2a, 0x04 }, + { OV511_I2C_BUS, 0x2c, 0xfe }, + { OV511_I2C_BUS, 0x30, 0x71 }, + { OV511_I2C_BUS, 0x31, 0x60 }, + { OV511_I2C_BUS, 0x32, 0x26 }, + { OV511_I2C_BUS, 0x33, 0x20 }, + { OV511_I2C_BUS, 0x34, 0x48 }, + { OV511_I2C_BUS, 0x12, 0x24 }, + { OV511_I2C_BUS, 0x11, 0x01 }, + { OV511_I2C_BUS, 0x0c, 0x24 }, + { OV511_I2C_BUS, 0x0d, 0x24 }, + { OV511_DONE_BUS, 0x0, 0x00 }, }; - static struct ov511_regvals aRegvalsNorm7620[] = - {{OV511_I2C_BUS, 0x10, 0xff}, - {OV511_I2C_BUS, 0x16, 0x06}, - {OV511_I2C_BUS, 0x28, 0x24}, - {OV511_I2C_BUS, 0x2b, 0xac}, - {OV511_I2C_BUS, 0x12, 0x00}, - {OV511_I2C_BUS, 0x28, 0x24}, - {OV511_I2C_BUS, 0x05, 0x00}, - {OV511_I2C_BUS, 0x0f, 0x05}, - {OV511_I2C_BUS, 0x15, 0x01}, - {OV511_I2C_BUS, 0x23, 0x00}, - {OV511_I2C_BUS, 0x24, 0x10}, - {OV511_I2C_BUS, 0x25, 0x8a}, - {OV511_I2C_BUS, 0x27, 0xe2}, - {OV511_I2C_BUS, 0x29, 0x03}, - {OV511_I2C_BUS, 0x2a, 0x00}, - {OV511_I2C_BUS, 0x2c, 0xfe}, - {OV511_I2C_BUS, 0x30, 0x71}, - {OV511_I2C_BUS, 0x31, 0x60}, - {OV511_I2C_BUS, 0x32, 0x26}, - {OV511_I2C_BUS, 0x33, 0x20}, - {OV511_I2C_BUS, 0x34, 0x48}, - {OV511_I2C_BUS, 0x12, 0x24}, - {OV511_I2C_BUS, 0x11, 0x01}, - {OV511_I2C_BUS, 0x0c, 0x24}, - {OV511_I2C_BUS, 0x0d, 0x24}, - {OV511_DONE_BUS, 0x0, 0x00}, + static struct ov511_regvals aRegvalsNorm7620[] = { + { OV511_I2C_BUS, 0x10, 0xff }, + { OV511_I2C_BUS, 0x16, 0x06 }, + { OV511_I2C_BUS, 0x28, 0x24 }, + { OV511_I2C_BUS, 0x2b, 0xac }, + { OV511_I2C_BUS, 0x12, 0x00 }, + { OV511_I2C_BUS, 0x28, 0x24 }, + { OV511_I2C_BUS, 0x05, 0x00 }, + { OV511_I2C_BUS, 0x0f, 0x05 }, + { OV511_I2C_BUS, 0x15, 0x01 }, + { OV511_I2C_BUS, 0x23, 0x00 }, + { OV511_I2C_BUS, 0x24, 0x10 }, + { OV511_I2C_BUS, 0x25, 0x8a }, + { OV511_I2C_BUS, 0x27, 0xe2 }, + { OV511_I2C_BUS, 0x29, 0x03 }, + { OV511_I2C_BUS, 0x2a, 0x00 }, + { OV511_I2C_BUS, 0x2c, 0xfe }, + { OV511_I2C_BUS, 0x30, 0x71 }, + { OV511_I2C_BUS, 0x31, 0x60 }, + { OV511_I2C_BUS, 0x32, 0x26 }, + { OV511_I2C_BUS, 0x33, 0x20 }, + { OV511_I2C_BUS, 0x34, 0x48 }, + { OV511_I2C_BUS, 0x12, 0x24 }, + { OV511_I2C_BUS, 0x11, 0x01 }, + { OV511_I2C_BUS, 0x0c, 0x24 }, + { OV511_I2C_BUS, 0x0d, 0x24 }, + { OV511_DONE_BUS, 0x0, 0x00 }, }; + PDEBUG (4, "starting configuration"); + if(ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE, OV7610_I2C_WRITE_ID) < 0) return -1; @@ -2385,13 +2319,13 @@ err("Error detecting sensor type"); return -1; } else if((rc & 3) == 3) { - printk("ov511: Sensor is an OV7610\n"); + info("Sensor is an OV7610"); ov511->sensor = SEN_OV7610; } else if((rc & 3) == 1) { - printk("ov511: Sensor is an OV7620AE\n"); + info("Sensor is an OV7620AE"); ov511->sensor = SEN_OV7620AE; } else if((rc & 3) == 0) { - printk("ov511: Sensor is an OV7620\n"); + info("Sensor is an OV7620"); ov511->sensor = SEN_OV7620; } else { err("Unknown image sensor version: %d", rc & 3); @@ -2399,13 +2333,15 @@ } } else { /* sensor != 0; user overrode detection */ ov511->sensor = sensor; - printk("ov511: Sensor set to type %d\n", ov511->sensor); + info("Sensor set to type %d", ov511->sensor); } if (ov511->sensor == SEN_OV7620) { + PDEBUG(4, "Writing 7620 registers"); if (ov511_write_regvals(dev, aRegvalsNorm7620)) return -1; } else { + PDEBUG(4, "Writing 7610 registers"); if (ov511_write_regvals(dev, aRegvalsNorm7610)) return -1; } @@ -2438,34 +2374,35 @@ static int ov511_configure(struct usb_ov511 *ov511) { struct usb_device *dev = ov511->dev; + int i; - static struct ov511_regvals aRegvalsInit[] = - {{OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x7f}, - {OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01}, - {OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x7f}, - {OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01}, - {OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3f}, - {OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01}, - {OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3d}, - {OV511_DONE_BUS, 0x0, 0x00}, + static struct ov511_regvals aRegvalsInit[] = { + { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x7f }, + { OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 }, + { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x7f }, + { OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 }, + { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3f }, + { OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 }, + { OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3d }, + { OV511_DONE_BUS, 0x0, 0x00}, }; - static struct ov511_regvals aRegvalsNorm511[] = - {{OV511_REG_BUS, 0x20, 0x01}, - {OV511_REG_BUS, 0x52, 0x02}, - {OV511_REG_BUS, 0x52, 0x00}, - {OV511_REG_BUS, 0x31, 0x1f}, /* 0f */ - {OV511_REG_BUS, 0x70, 0x3f}, - {OV511_REG_BUS, 0x71, 0x3f}, - {OV511_REG_BUS, 0x72, 0x01}, - {OV511_REG_BUS, 0x73, 0x01}, - {OV511_REG_BUS, 0x74, 0x01}, - {OV511_REG_BUS, 0x75, 0x01}, - {OV511_REG_BUS, 0x76, 0x01}, - {OV511_REG_BUS, 0x77, 0x01}, - {OV511_REG_BUS, 0x78, 0x06}, - {OV511_REG_BUS, 0x79, 0x03}, - {OV511_DONE_BUS, 0x0, 0x00}, + static struct ov511_regvals aRegvalsNorm511[] = { + { OV511_REG_BUS, OV511_REG_DRAM_ENABLE_FLOW_CONTROL, 0x01 }, + { OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x02 }, + { OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x00 }, + { OV511_REG_BUS, OV511_REG_FIFO_BITMASK, 0x1f }, /* 0f */ + { OV511_REG_BUS, OV511_OMNICE_PREDICTION_HORIZ_Y, 0x3f }, + { OV511_REG_BUS, OV511_OMNICE_PREDICTION_HORIZ_UV, 0x3f }, + { OV511_REG_BUS, OV511_OMNICE_PREDICTION_VERT_Y, 0x01 }, + { OV511_REG_BUS, OV511_OMNICE_PREDICTION_VERT_UV, 0x01 }, + { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_HORIZ_Y, 0x01 }, + { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_HORIZ_UV, 0x01 }, + { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_VERT_Y, 0x01 }, + { OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_VERT_UV, 0x01 }, + { OV511_REG_BUS, OV511_OMNICE_ENABLE, 0x06 }, + { OV511_REG_BUS, OV511_OMNICE_LUT_ENABLE, 0x03 }, + { OV511_DONE_BUS, 0x0, 0x00 }, }; memcpy(&ov511->vdev, &ov511_template, sizeof(ov511_template)); @@ -2488,16 +2425,15 @@ /* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used * (using read() instead). */ - ov511->frame[0].width = DEFAULT_WIDTH; - ov511->frame[0].height = DEFAULT_HEIGHT; - ov511->frame[0].depth = 24; /**************/ - ov511->frame[0].bytes_read = 0; - ov511->frame[0].segment = 0; - ov511->frame[1].width = DEFAULT_WIDTH; - ov511->frame[1].height = DEFAULT_HEIGHT; - ov511->frame[1].depth = 24; - ov511->frame[1].bytes_read = 0; - ov511->frame[1].segment = 0; + for (i = 0; i < OV511_NUMFRAMES; i++) { + ov511->frame[i].width = DEFAULT_WIDTH; + ov511->frame[i].height = DEFAULT_HEIGHT; + ov511->frame[i].depth = 24; + ov511->frame[i].bytes_read = 0; + ov511->frame[i].segment = 0; + ov511->frame[i].format = VIDEO_PALETTE_RGB24; + ov511->frame[i].segsize = GET_SEGSIZE(ov511->frame[i].format); + } /* Initialize to DEFAULT_WIDTH, DEFAULT_HEIGHT, YUV4:2:0 */ @@ -2588,7 +2524,7 @@ PDEBUG (4, "CustomID = %d", ov511->customid); for (i = 0; clist[i].id >= 0; i++) { if (ov511->customid == clist[i].id) { - printk ("Camera: %s\n", clist[i].description); + info("camera: %s", clist[i].description); ov511->desc = i; break; } @@ -2606,6 +2542,11 @@ err("support for your camera."); } + /* Workaround for some applications that want data in RGB + * instead of BGR */ + if (force_rgb) + info("data format set to RGB"); + if (!ov511_configure(ov511)) { ov511->user = 0; init_MUTEX(&ov511->lock); /* to 1 == available */ @@ -2670,7 +2611,6 @@ } #ifdef CONFIG_PROC_FS - PDEBUG(3, "destroying /proc/ov511/video%d", ov511->vdev.minor); destroy_proc_ov511_cam(ov511); #endif @@ -2712,13 +2652,12 @@ static void __exit usb_ov511_exit(void) { + usb_deregister(&ov511_driver); + info("ov511 driver deregistered"); + #ifdef CONFIG_PROC_FS - PDEBUG(3, "destroying /proc/ov511"); proc_ov511_destroy(); #endif - - usb_deregister(&ov511_driver); - info("ov511 driver deregistered"); } module_init(usb_ov511_init); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/ov511.h linux/drivers/usb/ov511.h --- v2.3.99-pre8/linux/drivers/usb/ov511.h Thu May 11 15:30:08 2000 +++ linux/drivers/usb/ov511.h Sat May 20 10:37:04 2000 @@ -1,3 +1,4 @@ + #ifndef __LINUX_OV511_H #define __LINUX_OV511_H @@ -9,7 +10,7 @@ #ifdef OV511_DEBUG # define PDEBUG(level, fmt, args...) \ -if (debug >= level) printk("ov511: [" __PRETTY_FUNCTION__ ":%d] " fmt "\n", __LINE__ , ## args) +if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args) #else # define PDEBUG(level, fmt, args...) do {} while(0) #endif @@ -119,48 +120,55 @@ #define OV511PLUS_ALT_SIZE_961 7 /* OV7610 registers */ -#define OV7610_REG_GAIN 0x00 -#define OV7610_REG_BLUE 0x01 -#define OV7610_REG_RED 0x02 -#define OV7610_REG_SAT 0x03 -#define OV7610_REG_CNT 0x05 -#define OV7610_REG_BRT 0x06 -#define OV7610_REG_BLUE_BIAS 0x0C -#define OV7610_REG_RED_BIAS 0x0D -#define OV7610_REG_GAMMA_COEFF 0x0E -#define OV7610_REG_WB_RANGE 0x0F -#define OV7610_REG_EXP 0x10 -#define OV7610_REG_CLOCK 0x11 -#define OV7610_REG_COM_A 0x12 -#define OV7610_REG_COM_B 0x13 -#define OV7610_REG_COM_C 0x14 -#define OV7610_REG_COM_D 0x15 -#define OV7610_REG_FIELD_DIVIDE 0x16 -#define OV7610_REG_HWIN_START 0x17 -#define OV7610_REG_HWIN_END 0x18 -#define OV7610_REG_VWIN_START 0x19 -#define OV7610_REG_VWIN_END 0x1A -#define OV7610_REG_PIXEL_SHIFT 0x1B -#define OV7610_REG_ID_HIGH 0x1C -#define OV7610_REG_ID_LOW 0x1D -#define OV7610_REG_COM_E 0x20 -#define OV7610_REG_YOFFSET 0x21 -#define OV7610_REG_UOFFSET 0x22 -#define OV7610_REG_ECW 0x24 -#define OV7610_REG_ECB 0x25 -#define OV7610_REG_COM_F 0x26 -#define OV7610_REG_COM_G 0x27 -#define OV7610_REG_COM_H 0x28 -#define OV7610_REG_COM_I 0x29 -#define OV7610_REG_FRAMERATE_H 0x2A -#define OV7610_REG_FRAMERATE_L 0x2B -#define OV7610_REG_ALC 0x2C -#define OV7610_REG_COM_J 0x2D -#define OV7610_REG_VOFFSET 0x2E -#define OV7610_REG_YGAMMA 0x33 -#define OV7610_REG_BIAS_ADJUST 0x34 -#define OV7610_REG_COM_L 0x35 -#define OV7610_REG_COM_K 0x38 +#define OV7610_REG_GAIN 0x00 /* gain setting (5:0) */ +#define OV7610_REG_BLUE 0x01 /* blue channel balance */ +#define OV7610_REG_RED 0x02 /* red channel balance */ +#define OV7610_REG_SAT 0x03 /* saturation */ + /* 04 reserved */ +#define OV7610_REG_CNT 0x05 /* Y contrast */ +#define OV7610_REG_BRT 0x06 /* Y brightness */ + /* 08-0b reserved */ +#define OV7610_REG_BLUE_BIAS 0x0C /* blue channel bias (5:0) */ +#define OV7610_REG_RED_BIAS 0x0D /* read channel bias (5:0) */ +#define OV7610_REG_GAMMA_COEFF 0x0E /* gamma settings */ +#define OV7610_REG_WB_RANGE 0x0F /* AEC/ALC/S-AWB settings */ +#define OV7610_REG_EXP 0x10 /* manual exposure setting */ +#define OV7610_REG_CLOCK 0x11 /* polarity/clock prescaler */ +#define OV7610_REG_COM_A 0x12 /* misc common regs */ +#define OV7610_REG_COM_B 0x13 /* misc common regs */ +#define OV7610_REG_COM_C 0x14 /* misc common regs */ +#define OV7610_REG_COM_D 0x15 /* misc common regs */ +#define OV7610_REG_FIELD_DIVIDE 0x16 /* field interval/mode settings */ +#define OV7610_REG_HWIN_START 0x17 /* horizontal window start */ +#define OV7610_REG_HWIN_END 0x18 /* horizontal window end */ +#define OV7610_REG_VWIN_START 0x19 /* vertical window start */ +#define OV7610_REG_VWIN_END 0x1A /* vertical window end */ +#define OV7610_REG_PIXEL_SHIFT 0x1B /* pixel shift */ +#define OV7610_REG_ID_HIGH 0x1C /* manufacturer ID MSB */ +#define OV7610_REG_ID_LOW 0x1D /* manufacturer ID LSB */ + /* 0e-0f reserved */ +#define OV7610_REG_COM_E 0x20 /* misc common regs */ +#define OV7610_REG_YOFFSET 0x21 /* Y channel offset */ +#define OV7610_REG_UOFFSET 0x22 /* U channel offset */ + /* 23 reserved */ +#define OV7610_REG_ECW 0x24 /* Exposure white level for AEC */ +#define OV7610_REG_ECB 0x25 /* Exposure black level for AEC */ +#define OV7610_REG_COM_F 0x26 /* misc settings */ +#define OV7610_REG_COM_G 0x27 /* misc settings */ +#define OV7610_REG_COM_H 0x28 /* misc settings */ +#define OV7610_REG_COM_I 0x29 /* misc settings */ +#define OV7610_REG_FRAMERATE_H 0x2A /* frame rate MSB + misc */ +#define OV7610_REG_FRAMERATE_L 0x2B /* frame rate LSB */ +#define OV7610_REG_ALC 0x2C /* Auto Level Control settings */ +#define OV7610_REG_COM_J 0x2D /* misc settings */ +#define OV7610_REG_VOFFSET 0x2E /* V channel offset adjustment */ +#define OV7610_REG_ARRAY_BIAS 0x2F /* Array bias -- don't change */ + /* 30-32 reserved */ +#define OV7610_REG_YGAMMA 0x33 /* misc gamma settings (7:6) */ +#define OV7610_REG_BIAS_ADJUST 0x34 /* misc bias settings */ +#define OV7610_REG_COM_L 0x35 /* misc settings */ + /* 36-37 reserved */ +#define OV7610_REG_COM_K 0x38 /* misc registers */ #define STREAM_BUF_SIZE (PAGE_SIZE * 4) @@ -171,8 +179,7 @@ #define FRAME_SIZE_PER_DESC 993 /* FIXME - Deprecated */ #define MAX_FRAME_SIZE_PER_DESC 993 /* For statically allocated stuff */ -// FIXME - should this be 0x81 (endpoint address) or 0x01 (endpoint number)? -#define OV511_ENDPOINT_ADDRESS 0x81 /* Address of isoc endpoint */ +#define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */ // CAMERA SPECIFIC // FIXME - these can vary between specific models @@ -223,9 +230,9 @@ struct ov511_regvals { enum { - OV511_DONE_BUS, - OV511_REG_BUS, - OV511_I2C_BUS, + OV511_DONE_BUS, + OV511_REG_BUS, + OV511_I2C_BUS, } bus; unsigned char reg; unsigned char val; @@ -269,15 +276,16 @@ /* Device structure */ struct usb_device *dev; -#if 0 - unsigned char customid; /* Type of camera */ -#else int customid; int desc; -#endif - unsigned char iface; + int brightness; + int colour; + int contrast; + int hue; + int whiteness; + struct semaphore lock; int user; /* user count for exclusive use */ @@ -318,10 +326,33 @@ struct proc_dir_entry *proc_entry; /* /proc/ov511/videoX */ }; - struct cam_list { int id; char *description; +}; + +struct palette_list { + int num; + char *name; +}; + +struct mode_list { + int width; + int height; + int mode; + u8 pxcnt; + u8 lncnt; + u8 pxdv; + u8 lndv; + u8 s_pxcnt; + u8 s_lncnt; + u8 s_pxdv; + u8 s_lndv; + u8 clock; + u8 m420; + u8 common_A; + u8 common_C; + u8 common_L; }; #endif diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/pegasus.c linux/drivers/usb/pegasus.c --- v2.3.99-pre8/linux/drivers/usb/pegasus.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/pegasus.c Tue May 23 08:22:22 2000 @@ -16,7 +16,7 @@ #include -static const char *version = __FILE__ ": v0.3.9 2000/04/11 Written by Petko Manolov (petkan@spct.net)\n"; +static const char *version = __FILE__ ": v0.3.12 2000/05/22 (C) 1999-2000 Petko Manolov (petkan@spct.net)\n"; #define PEGASUS_MTU 1500 @@ -24,12 +24,15 @@ #define SROM_WRITE 0x01 #define SROM_READ 0x02 #define PEGASUS_TX_TIMEOUT (HZ*5) +#define PEGASUS_RESET 1 #define ALIGN(x) x __attribute__((aligned(L1_CACHE_BYTES))) + struct pegasus { struct usb_device *usb; struct net_device *net; struct net_device_stats stats; + int flags; spinlock_t pegasus_lock; struct urb rx_urb, tx_urb, intr_urb; unsigned char ALIGN(rx_buff[PEGASUS_MAX_MTU]); @@ -44,9 +47,11 @@ void *private; }; + static int loopback = 0; static int multicast_filter_limit = 32; + MODULE_AUTHOR("Petko Manolov "); MODULE_DESCRIPTION("ADMtek AN986 Pegasus USB Ethernet driver"); MODULE_PARM(loopback, "i"); @@ -98,6 +103,7 @@ return 1; } + static int pegasus_write_phy_word(struct usb_device *dev, __u8 index, __u16 regdata) { int i; @@ -115,6 +121,7 @@ return 1; } + static int pegasus_rw_srom_word(struct usb_device *dev, __u8 index, __u16 *retdata, __u8 direction) { int i; @@ -134,6 +141,7 @@ return 1; } + static int pegasus_get_node_id(struct usb_device *dev, __u8 *id) { int i; @@ -143,6 +151,7 @@ return 0; } + static int pegasus_reset_mac(struct usb_device *dev) { __u8 data = 0x8; @@ -165,6 +174,7 @@ return 1; } + static int pegasus_start_net(struct net_device *dev, struct usb_device *usb) { __u16 partmedia, temp; @@ -195,13 +205,14 @@ data[0] = 0xc9; data[1] = (partmedia & 0x100) ? 0x30 : ((partmedia & 0x80) ? 0x10 : 0); - data[2] = (loopback & 1) ? 0x08 : 0x00; + data[2] = (loopback & 1) ? 0x09 : 0x01; pegasus_set_registers(usb, 0, 3, data); return 0; } + static void pegasus_read_bulk(struct urb *urb) { struct pegasus *pegasus = urb->context; @@ -253,15 +264,16 @@ warn("(prb)failed rx_urb %d", res); } + static void pegasus_irq(urb_t *urb) { - if(urb->status) { - __u8 *d = urb->transfer_buffer; - printk("txst0 %x, txst1 %x, rxst %x, rxlst0 %x, rxlst1 %x, wakest %x", - d[0], d[1], d[2], d[3], d[4], d[5]); - } + __u8 *d = urb->transfer_buffer; + + if ( d[0] ) + dbg("txst0=0x%2x", d[0]); } + static void pegasus_write_bulk(struct urb *urb) { struct pegasus *pegasus = urb->context; @@ -280,12 +292,15 @@ struct pegasus *pegasus = net->priv; warn("%s: Tx timed out. Reseting...", net->name); + usb_unlink_urb(&pegasus->tx_urb); pegasus->stats.tx_errors++; net->trans_start = jiffies; + pegasus->flags |= PEGASUS_RESET; netif_wake_queue(net); } + static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net) { struct pegasus *pegasus = net->priv; @@ -317,11 +332,13 @@ return 0; } + static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev) { return &((struct pegasus *)dev->priv)->stats; } + static int pegasus_open(struct net_device *net) { struct pegasus *pegasus = (struct pegasus *)net->priv; @@ -334,8 +351,10 @@ if ((res = usb_submit_urb(&pegasus->rx_urb))) warn("(open)failed rx_urb %d", res); - -/* usb_submit_urb(&pegasus->intr_urb);*/ + + if ((res = usb_submit_urb(&pegasus->intr_urb))) + warn("(open)failed intr_urb %d", res); + netif_start_queue(net); MOD_INC_USE_COUNT; @@ -343,6 +362,7 @@ return 0; } + static int pegasus_close(struct net_device *net) { struct pegasus *pegasus = net->priv; @@ -351,13 +371,14 @@ usb_unlink_urb(&pegasus->rx_urb); usb_unlink_urb(&pegasus->tx_urb); -/* usb_unlink_urb(&pegasus->intr_urb); */ + usb_unlink_urb(&pegasus->intr_urb); MOD_DEC_USE_COUNT; return 0; } + static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd) { __u16 *data = (__u16 *)&rq->ifr_data; @@ -379,6 +400,7 @@ } } + static void pegasus_set_rx_mode(struct net_device *net) { struct pegasus *pegasus = net->priv; @@ -400,6 +422,7 @@ netif_wake_queue(net); } + static int check_device_ids( __u16 vendor, __u16 product ) { int i=0; @@ -413,6 +436,7 @@ return -1; } + static void * pegasus_probe(struct usb_device *dev, unsigned int ifnum) { struct net_device *net; @@ -463,7 +487,7 @@ pegasus->tx_buff, PEGASUS_MAX_MTU, pegasus_write_bulk, pegasus); FILL_INT_URB(&pegasus->intr_urb, dev, usb_rcvintpipe(dev, 3), - pegasus->intr_buff, 8, pegasus_irq, pegasus, 250); + pegasus->intr_buff, 8, pegasus_irq, pegasus, 500); printk(KERN_INFO "%s: %s\n", net->name, usb_dev_id[dev_indx].name); @@ -471,6 +495,7 @@ return pegasus; } + static void pegasus_disconnect(struct usb_device *dev, void *ptr) { struct pegasus *pegasus = ptr; @@ -487,10 +512,11 @@ usb_unlink_urb(&pegasus->rx_urb); usb_unlink_urb(&pegasus->tx_urb); -/* usb_unlink_urb(&pegasus->intr_urb);*/ + usb_unlink_urb(&pegasus->intr_urb); kfree(pegasus); } + static struct usb_driver pegasus_driver = { name: "pegasus", diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/printer.c linux/drivers/usb/printer.c --- v2.3.99-pre8/linux/drivers/usb/printer.c Wed Apr 26 16:34:08 2000 +++ linux/drivers/usb/printer.c Mon May 15 11:38:12 2000 @@ -1,5 +1,5 @@ /* - * printer.c Version 0.3 + * printer.c Version 0.4 * * Copyright (c) 1999 Michael Gee * Copyright (c) 1999 Pavel Machek @@ -13,6 +13,7 @@ * v0.1 - thorough cleaning, URBification, almost a rewrite * v0.2 - some more cleanups * v0.3 - cleaner again, waitqueue fixes + * v0.4 - fixes in unidirectional mode */ /* @@ -102,7 +103,7 @@ return; if (urb->status) - warn("nonzero read bulk status received: %d", urb->status); + warn("nonzero read/write bulk status received: %d", urb->status); wake_up_interruptible(&usblp->wait); } @@ -172,9 +173,12 @@ usblp->writeurb.transfer_buffer_length = 0; usblp->writeurb.status = 0; - usblp->readcount = 0; - usb_submit_urb(&usblp->readurb); + if (usblp->bidir) { + usblp->readcount = 0; + usb_submit_urb(&usblp->readurb); + } + return 0; } @@ -185,7 +189,8 @@ usblp->used = 0; if (usblp->dev) { - usb_unlink_urb(&usblp->readurb); + if (usblp->bidir) + usb_unlink_urb(&usblp->readurb); usb_unlink_urb(&usblp->writeurb); MOD_DEC_USE_COUNT; return 0; @@ -203,8 +208,8 @@ { struct usblp *usblp = file->private_data; poll_wait(file, &usblp->wait, wait); - return (usblp->readurb.status == -EINPROGRESS ? 0 : POLLIN | POLLRDNORM) - | (usblp->writeurb.status == -EINPROGRESS ? 0 : POLLOUT | POLLWRNORM); + return ((usblp->bidir || usblp->readurb.status == -EINPROGRESS) ? 0 : POLLIN | POLLRDNORM) + | (usblp->writeurb.status == -EINPROGRESS ? 0 : POLLOUT | POLLWRNORM); } static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) @@ -315,7 +320,6 @@ int minor, i, alts = -1, bidir = 0; char *buf; - for (i = 0; i < dev->actconfig->interface[ifnum].num_altsetting; i++) { interface = &dev->actconfig->interface[ifnum].altsetting[i]; @@ -342,22 +346,21 @@ err("can't set desired altsetting %d on interface %d", alts, ifnum); epwrite = interface->endpoint + 0; - epread = NULL; - - if (bidir) { - epread = interface->endpoint + 1; - if ((epread->bEndpointAddress & 0x80) != 0x80) { - epwrite = interface->endpoint + 1; - epread = interface->endpoint + 0; + epread = bidir ? interface->endpoint + 1 : NULL; - if ((epread->bEndpointAddress & 0x80) != 0x80) - return NULL; - } + if ((epwrite->bEndpointAddress & 0x80) == 0x80) { + if (interface->bNumEndpoints == 1) + return NULL; + epwrite = interface->endpoint + 1; + epread = bidir ? interface->endpoint + 0 : NULL; } if ((epwrite->bEndpointAddress & 0x80) == 0x80) return NULL; + if (bidir && (epread->bEndpointAddress & 0x80) != 0x80) + return NULL; + for (minor = 0; minor < USBLP_MINORS && usblp_table[minor]; minor++); if (usblp_table[minor]) { err("no more free usblp devices"); @@ -386,10 +389,9 @@ FILL_BULK_URB(&usblp->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress), buf, 0, usblp_bulk, usblp); - if (bidir) { + if (bidir) FILL_BULK_URB(&usblp->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress), buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE, usblp_bulk, usblp); - } info("usblp%d: USB %sdirectional printer dev %d if %d alt %d", minor, bidir ? "Bi" : "Uni", dev->devnum, ifnum, alts); @@ -408,8 +410,9 @@ usblp->dev = NULL; - usb_unlink_urb(&usblp->readurb); usb_unlink_urb(&usblp->writeurb); + if (usblp->bidir) + usb_unlink_urb(&usblp->readurb); kfree(usblp->writeurb.transfer_buffer); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/Makefile linux/drivers/usb/serial/Makefile --- v2.3.99-pre8/linux/drivers/usb/serial/Makefile Thu May 11 15:30:08 2000 +++ linux/drivers/usb/serial/Makefile Tue May 23 08:21:51 2000 @@ -4,8 +4,26 @@ O_TARGET := usb-serial.o M_OBJS := usb-serial.o -O_OBJS := usbserial.o visor.o whiteheat.o ftdi_sio.o keyspan_pda.o omninet.o digi_acceleport.o +O_OBJS := usbserial.o MOD_LIST_NAME := USB_SERIAL_MODULES +ifeq ($(CONFIG_USB_SERIAL_VISOR),y) + O_OBJS += visor.o +endif +ifeq ($(CONFIG_USB_SERIAL_WHITEHEAT),y) + O_OBJS += whiteheat.o +endif +ifeq ($(CONFIG_USB_SERIAL_FTDI_SIO),y) + O_OBJS += ftdi_sio.o +endif +ifeq ($(CONFIG_USB_SERIAL_KEYSPAN_PDA),y) + O_OBJS += keyspan_pda.o +endif +ifeq ($(CONFIG_USB_SERIAL_OMNINET),y) + O_OBJS += omninet.o +endif +ifeq ($(CONFIG_USB_SERIAL_DIGI_ACCELEPORT),y) + O_OBJS += digi_acceleport.o +endif + include $(TOPDIR)/Rules.make - diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/digi_acceleport.c linux/drivers/usb/serial/digi_acceleport.c --- v2.3.99-pre8/linux/drivers/usb/serial/digi_acceleport.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/serial/digi_acceleport.c Tue May 23 08:21:51 2000 @@ -14,16 +14,39 @@ * Peter Berger (pberger@brimson.com) * Al Borchers (borchers@steinerpoint.com) * +* (5/16/2000) pberger and borchers +* -- added timeouts to sleeps +* -- handle transition to/from B0 in digi_set_termios +* +* (5/13/2000) pberger and borchers +* -- all commands now sent on out of band port, using digi_write_oob +* -- get modem control signals whenever they change, support TIOCMGET/ +* SET/BIS/BIC ioctls +* -- digi_set_termios now supports parity, word size, stop bits, and +* receive enable +* -- cleaned up open and close, use digi_set_termios and digi_write_oob +* to set port parameters +* -- added digi_startup_device to start read chains on all ports +* -- write buffer is only used when count==1, to be sure put_char can +* write a char (unless the buffer is full) +* +* (5/10/2000) pberger and borchers +* -- Added MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT calls +* -- Fixed problem where the first incoming character is lost on +* port opens after the first close on that port. Now we keep +* the read_urb chain open until shutdown. +* -- Added more port conditioning calls in digi_open and digi_close. +* -- Convert port->active to a use count so that we can deal with multiple +* opens and closes properly. +* -- Fixed some problems with the locking code. +* * (5/3/2000) pberger and borchers -* First alpha version of the driver--many known limitations and bugs. +* -- First alpha version of the driver--many known limitations and bugs. * -* $Id: digi_acceleport.c,v 1.28 2000/05/04 01:47:08 root Exp root $ +* $Id: digi_acceleport.c,v 1.43 2000/05/17 03:21:38 root Exp root $ */ #include - -#ifdef CONFIG_USB_SERIAL_DIGI_ACCELEPORT - #include #include #include @@ -37,45 +60,57 @@ #include #include #include +#include +#include "usb-serial.h" #ifdef CONFIG_USB_SERIAL_DEBUG #define DEBUG #else #undef DEBUG #endif -#include -#include "usb-serial.h" /* Defines */ /* port buffer length -- must be <= transfer buffer length - 2 */ /* so we can be sure to send the full buffer in one urb */ -#define DIGI_PORT_BUF_LEN 16 +#define DIGI_PORT_BUF_LEN 16 + +/* retry timeout while waiting for urb->status to go to 0 */ +#define DIGI_RETRY_TIMEOUT (HZ/10) /* AccelePort USB Defines */ /* ids */ -#define DIGI_VENDOR_ID 0x05c5 -#define DIGI_ID 0x0004 +#define DIGI_VENDOR_ID 0x05c5 +#define DIGI_ID 0x0004 -/* commands */ -#define DIGI_CMD_SET_BAUD_RATE 0 -#define DIGI_CMD_SET_WORD_SIZE 1 -#define DIGI_CMD_SET_PARITY 2 -#define DIGI_CMD_SET_STOP_BITS 3 -#define DIGI_CMD_SET_INPUT_FLOW_CONTROL 4 -#define DIGI_CMD_SET_OUTPUT_FLOW_CONTROL 5 -#define DIGI_CMD_SET_DTR_SIGNAL 6 -#define DIGI_CMD_SET_RTS_SIGNAL 7 -#define DIGI_CMD_RECEIVE_ENABLE 10 -#define DIGI_CMD_BREAK_CONTROL 11 -#define DIGI_CMD_LOCAL_LOOPBACK 12 -#define DIGI_CMD_TRANSMIT_IDLE 13 -#define DIGI_CMD_WRITE_UART_REGISTER 15 -#define DIGI_CMD_AND_UART_REGISTER 16 -#define DIGI_CMD_OR_UART_REGISTER 17 -#define DIGI_CMD_SEND_DATA 18 +/* commands + * "INB": can be used on the in-band endpoint + * "OOB": can be used on the out-of-band endpoint + */ +#define DIGI_CMD_SET_BAUD_RATE 0 /* INB, OOB */ +#define DIGI_CMD_SET_WORD_SIZE 1 /* INB, OOB */ +#define DIGI_CMD_SET_PARITY 2 /* INB, OOB */ +#define DIGI_CMD_SET_STOP_BITS 3 /* INB, OOB */ +#define DIGI_CMD_SET_INPUT_FLOW_CONTROL 4 /* INB, OOB */ +#define DIGI_CMD_SET_OUTPUT_FLOW_CONTROL 5 /* INB, OOB */ +#define DIGI_CMD_SET_DTR_SIGNAL 6 /* INB, OOB */ +#define DIGI_CMD_SET_RTS_SIGNAL 7 /* INB, OOB */ +#define DIGI_CMD_READ_INPUT_SIGNALS 8 /* OOB */ +#define DIGI_CMD_IFLUSH_FIFO 9 /* OOB */ +#define DIGI_CMD_RECEIVE_ENABLE 10 /* INB, OOB */ +#define DIGI_CMD_BREAK_CONTROL 11 /* INB, OOB */ +#define DIGI_CMD_LOCAL_LOOPBACK 12 /* INB, OOB */ +#define DIGI_CMD_TRANSMIT_IDLE 13 /* INB, OOB */ +#define DIGI_CMD_READ_UART_REGISTER 14 /* OOB */ +#define DIGI_CMD_WRITE_UART_REGISTER 15 /* INB, OOB */ +#define DIGI_CMD_AND_UART_REGISTER 16 /* INB, OOB */ +#define DIGI_CMD_OR_UART_REGISTER 17 /* INB, OOB */ +#define DIGI_CMD_SEND_DATA 18 /* INB */ +#define DIGI_CMD_RECEIVE_DATA 19 /* INB */ +#define DIGI_CMD_RECEIVE_DISABLE 20 /* INB */ +#define DIGI_CMD_GET_PORT_TYPE 21 /* OOB */ /* baud rates */ #define DIGI_BAUD_50 0 @@ -102,10 +137,71 @@ #define DIGI_BAUD_230400 21 #define DIGI_BAUD_460800 22 -/* flow control arguments */ -#define DIGI_ENABLE_IXON_IXOFF_FLOW_CONTROL 1 -#define DIGI_ENABLE_RTS_CTS_FLOW_CONTROL 2 -#define DIGI_ENABLE_DTR_DSR_FLOW_CONTROL 4 +/* arguments */ +#define DIGI_WORD_SIZE_5 0 +#define DIGI_WORD_SIZE_6 1 +#define DIGI_WORD_SIZE_7 2 +#define DIGI_WORD_SIZE_8 3 + +#define DIGI_PARITY_NONE 0 +#define DIGI_PARITY_ODD 1 +#define DIGI_PARITY_EVEN 2 +#define DIGI_PARITY_MARK 3 +#define DIGI_PARITY_SPACE 4 + +#define DIGI_STOP_BITS_1 0 +#define DIGI_STOP_BITS_2 1 + +#define DIGI_INPUT_FLOW_CONTROL_XON_XOFF 1 +#define DIGI_INPUT_FLOW_CONTROL_RTS 2 +#define DIGI_INPUT_FLOW_CONTROL_DTR 4 + +#define DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF 1 +#define DIGI_OUTPUT_FLOW_CONTROL_CTS 2 +#define DIGI_OUTPUT_FLOW_CONTROL_DSR 4 + +#define DIGI_DTR_INACTIVE 0 +#define DIGI_DTR_ACTIVE 1 +#define DIGI_DTR_INPUT_FLOW_CONTROL 2 + +#define DIGI_RTS_INACTIVE 0 +#define DIGI_RTS_ACTIVE 1 +#define DIGI_RTS_INPUT_FLOW_CONTROL 2 +#define DIGI_RTS_TOGGLE 3 + +#define DIGI_FLUSH_TX 1 +#define DIGI_FLUSH_RX 2 +#define DIGI_RESUME_TX 4 /* clears xoff condition */ + +#define DIGI_DISABLE 0 +#define DIGI_ENABLE 1 + +#define DIGI_DEASSERT 0 +#define DIGI_ASSERT 1 + +/* in band status codes */ +#define DIGI_OVERRUN_ERROR 4 +#define DIGI_PARITY_ERROR 8 +#define DIGI_FRAMING_ERROR 16 +#define DIGI_BREAK_ERROR 32 + +/* out of band status */ +#define DIGI_NO_ERROR 0 +#define DIGI_BAD_FIRST_PARAMETER 1 +#define DIGI_BAD_SECOND_PARAMETER 2 +#define DIGI_INVALID_LINE 3 +#define DIGI_INVALID_OPCODE 4 + +/* input signals */ +#define DIGI_READ_INPUT_SIGNALS_SLOT 1 +#define DIGI_READ_INPUT_SIGNALS_ERR 2 +#define DIGI_READ_INPUT_SIGNALS_BUSY 4 +#define DIGI_READ_INPUT_SIGNALS_PE 8 +#define DIGI_READ_INPUT_SIGNALS_CTS 16 +#define DIGI_READ_INPUT_SIGNALS_DSR 32 +#define DIGI_READ_INPUT_SIGNALS_RI 64 +#define DIGI_READ_INPUT_SIGNALS_DCD 128 + /* macros */ #define MAX(a,b) (((a)>(b))?(a):(b)) @@ -117,32 +213,21 @@ typedef struct digi_private { spinlock_t dp_port_lock; int dp_buf_len; - char dp_buf[32]; + unsigned char dp_buf[DIGI_PORT_BUF_LEN]; + unsigned int dp_modem_signals; } digi_private_t; -struct s_digiusb { - u8 opcode; - u8 length; - u8 val; - u8 pad; -}; - /* Local Function Declarations */ -static void digi_send_cmd( char *mes, struct usb_serial_port *port, int opcode, - int length, int val ); -static void digi_send_oob( char *mes, int opcode, int linenum, int data1, int data2 ); +static int digi_write_oob( unsigned char *buf, int count ); +static int digi_set_modem_signals( struct usb_serial_port *port, + unsigned int modem_signals ); static void digi_rx_throttle (struct usb_serial_port *port); static void digi_rx_unthrottle (struct usb_serial_port *port); -static int digi_setbaud( struct usb_serial_port *port, int baud ); static void digi_set_termios( struct usb_serial_port *port, struct termios *old_termios ); static void digi_break_ctl( struct usb_serial_port *port, int break_state ); -static int digi_get_modem_info( struct usb_serial *serial, - unsigned char *value ); -static int digi_set_modem_info( struct usb_serial *serial, - unsigned char value ); static int digi_ioctl( struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg ); static int digi_write( struct usb_serial_port *port, int from_user, @@ -152,138 +237,186 @@ static int digi_chars_in_buffer( struct usb_serial_port *port ); static int digi_open( struct usb_serial_port *port, struct file *filp ); static void digi_close( struct usb_serial_port *port, struct file *filp ); -static int digi_startup (struct usb_serial *serial); +static int digi_startup_device( struct usb_serial *serial ); +static int digi_startup( struct usb_serial *serial ); static void digi_shutdown( struct usb_serial *serial ); static void digi_read_bulk_callback( struct urb *urb ); +static void digi_read_oob( struct urb *urb ); /* Statics */ /* device info needed for the Digi serial converter */ -static __u16 digi_vendor_id = DIGI_VENDOR_ID; -static __u16 digi_product_id = DIGI_ID; +static __u16 digi_vendor_id = DIGI_VENDOR_ID; +static __u16 digi_product_id = DIGI_ID; /* out of band port */ -static int oob_port_num; /* index of out-of-band port */ -static struct usb_serial_port *oob_port; /* out-of-band control port */ -static int oob_read_started = 0; +static int oob_port_num; /* index of out-of-band port */ +static struct usb_serial_port *oob_port; /* out-of-band port */ +static int device_startup = 0; -/* config lock -- used to protect digi statics and globals, like oob vars */ -spinlock_t config_lock; +/* startup lock -- used to by digi_startup_device */ +spinlock_t startup_lock; /* Globals */ struct usb_serial_device_type digi_acceleport_device = { - name: "Digi USB", - idVendor: &digi_vendor_id, - idProduct: &digi_product_id, - needs_interrupt_in: DONT_CARE, - needs_bulk_in: MUST_HAVE, - needs_bulk_out: MUST_HAVE, - num_interrupt_in: 0, - num_bulk_in: 5, - num_bulk_out: 5, - num_ports: 4, - open: digi_open, - close: digi_close, - write: digi_write, - write_room: digi_write_room, - write_bulk_callback: digi_write_bulk_callback, - read_bulk_callback: digi_read_bulk_callback, - chars_in_buffer: digi_chars_in_buffer, - throttle: digi_rx_throttle, - unthrottle: digi_rx_unthrottle, - ioctl: digi_ioctl, - set_termios: digi_set_termios, - break_ctl: digi_break_ctl, - startup: digi_startup, - shutdown: digi_shutdown, + name: "Digi USB", + idVendor: &digi_vendor_id, + idProduct: &digi_product_id, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: MUST_HAVE, + needs_bulk_out: MUST_HAVE, + num_interrupt_in: 0, + num_bulk_in: 5, + num_bulk_out: 5, + num_ports: 4, + open: digi_open, + close: digi_close, + write: digi_write, + write_room: digi_write_room, + write_bulk_callback: digi_write_bulk_callback, + read_bulk_callback: digi_read_bulk_callback, + chars_in_buffer: digi_chars_in_buffer, + throttle: digi_rx_throttle, + unthrottle: digi_rx_unthrottle, + ioctl: digi_ioctl, + set_termios: digi_set_termios, + break_ctl: digi_break_ctl, + startup: digi_startup, + shutdown: digi_shutdown, }; /* Functions */ -/* Send message on the out-of-Band endpoint */ -static void digi_send_oob( char *mes, int opcode, int linenum, int data1, int data2 ) +/* +* Digi Write OOB +* +* Write commands on the out of band port. Commands are 4 +* bytes each, multiple commands can be sent at once, and +* no command will be split across USB packets. Returns 0 +* if successful, -EINTR if interrupted while sleeping, or +* a negative error returned by usb_submit_urb. +*/ + +static int digi_write_oob( unsigned char *buf, int count ) { - int ret; - struct s_digiusb digiusb; - digi_private_t *priv = (digi_private_t *)(oob_port->private); + int ret = 0; + int len; + digi_private_t *oob_priv = (digi_private_t *)(oob_port->private); -dbg( "digi_send_oob: TOP: from '%s', opcode: %d, linenum:%d, data1: %d, data2: %d", mes, opcode, linenum, data1, data2 ); - digiusb.opcode = (u8)opcode; - digiusb.length = (u8)linenum; - digiusb.val = (u8)data1; - digiusb.pad = (u8)data2; +dbg( "digi_write_oob: TOP: port=%d, count=%d", oob_port->number, count ); - spin_lock( &priv->dp_port_lock ); + spin_lock( &oob_priv->dp_port_lock ); - while (oob_port->write_urb->status == -EINPROGRESS) { -dbg( "digi_send_oob: opcode:%d already writing...", opcode ); - spin_unlock( &priv->dp_port_lock ); - interruptible_sleep_on(&oob_port->write_wait); - if (signal_pending(current)) { - return; + while( count > 0 ) { + + while( oob_port->write_urb->status == -EINPROGRESS ) { + spin_unlock( &oob_priv->dp_port_lock ); + interruptible_sleep_on_timeout( &oob_port->write_wait, + DIGI_RETRY_TIMEOUT ); + if( signal_pending(current) ) { + return( -EINTR ); + } + spin_lock( &oob_priv->dp_port_lock ); + } + + /* len must be a multiple of 4, so commands are not split */ + len = MIN( count, oob_port->bulk_out_size ); + if( len > 4 ) + len &= ~3; + + memcpy( oob_port->write_urb->transfer_buffer, buf, len ); + oob_port->write_urb->transfer_buffer_length = len; + + if( (ret=usb_submit_urb(oob_port->write_urb)) == 0 ) { + count -= len; + buf += len; + } else { + dbg( "digi_write_oob: usb_submit_urb failed, ret=%d", + ret ); + break; } - spin_lock( &priv->dp_port_lock ); - } - memcpy( oob_port->write_urb->transfer_buffer, &digiusb, sizeof(digiusb) ); - oob_port->write_urb->transfer_buffer_length = sizeof(digiusb); - if( (ret=usb_submit_urb(oob_port->write_urb)) != 0 ) { - dbg( - "digi_send_oob: usb_submit_urb(write bulk) failed, opcode=%d, ret=%d", - opcode, ret ); } - spin_unlock( &priv->dp_port_lock ); + spin_unlock( &oob_priv->dp_port_lock ); -dbg( "digi_send_oob: opcode %d done", opcode ); + return( ret ); } -static void digi_send_cmd( char *mes, struct usb_serial_port *port, int opcode, - int length, int val ) +/* +* Digi Set Modem Signals +* +* Sets or clears DTR and RTS on the port, according to the +* modem_signals argument. Use TIOCM_DTR and TIOCM_RTS flags +* for the modem_signals argument. Returns 0 if successful, +* -EINTR if interrupted while sleeping, or a non-zero error +* returned by usb_submit_urb. +*/ + +static int digi_set_modem_signals( struct usb_serial_port *port, + unsigned int modem_signals ) { int ret; - struct s_digiusb digiusb; - digi_private_t *priv = (digi_private_t *)(port->private); - + unsigned char *data = oob_port->write_urb->transfer_buffer; + digi_private_t *port_priv = (digi_private_t *)(port->private); + digi_private_t *oob_priv = (digi_private_t *)(oob_port->private); -dbg( "digi_send_cmd: TOP: from '%s', opcode: %d, val: %d", mes, opcode, val ); - digiusb.opcode = (u8)opcode; - digiusb.length = (u8)length; - digiusb.val = (u8)val; - digiusb.pad = 0; +dbg( "digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x", +port->number, modem_signals ); - spin_lock( &priv->dp_port_lock ); + spin_lock( &oob_priv->dp_port_lock ); + spin_lock( &port_priv->dp_port_lock ); - while( port->write_urb->status == -EINPROGRESS ) { -dbg( "digi_send_cmd: opcode=%d already writing...", opcode ); - spin_unlock( &priv->dp_port_lock ); - interruptible_sleep_on( &port->write_wait ); + while( oob_port->write_urb->status == -EINPROGRESS ) { + spin_unlock( &port_priv->dp_port_lock ); + spin_unlock( &oob_priv->dp_port_lock ); + interruptible_sleep_on_timeout( &oob_port->write_wait, + DIGI_RETRY_TIMEOUT ); if( signal_pending(current) ) { - return; + return( -EINTR ); } - spin_lock( &priv->dp_port_lock ); + spin_lock( &oob_priv->dp_port_lock ); + spin_lock( &port_priv->dp_port_lock ); } - memcpy( port->write_urb->transfer_buffer, &digiusb, sizeof(digiusb) ); - port->write_urb->transfer_buffer_length = sizeof(digiusb); - if( (ret=usb_submit_urb(port->write_urb)) != 0 ) - dbg( - "digi_send_cmd: usb_submit_urb(write bulk) failed, opcode=%d, ret=%d", - opcode, ret ); + /* command is 4 bytes: command, line, argument, pad */ + data[0] = DIGI_CMD_SET_DTR_SIGNAL; + data[1] = port->number; + data[2] = (modem_signals&TIOCM_DTR) ? + DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE; + data[3] = 0; + + data[4] = DIGI_CMD_SET_RTS_SIGNAL; + data[5] = port->number; + data[6] = (modem_signals&TIOCM_RTS) ? + DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE; + data[7] = 0; + + oob_port->write_urb->transfer_buffer_length = 8; + + if( (ret=usb_submit_urb(oob_port->write_urb)) == 0 ) { + port_priv->dp_modem_signals = + (port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS)) + | (modem_signals&(TIOCM_DTR|TIOCM_RTS)); + } else { + dbg( "digi_set_modem_signals: usb_submit_urb failed, ret=%d", + ret ); + } -dbg( "digi_send_cmd: opcode %d done", opcode ); + spin_unlock( &port_priv->dp_port_lock ); + spin_unlock( &oob_priv->dp_port_lock ); - spin_unlock( &priv->dp_port_lock ); + return( ret ); } @@ -312,52 +445,7 @@ /* just restart the receive interrupt URB */ //if (usb_submit_urb(port->interrupt_in_urb)) - // dbg( "digi_rx_unthrottle: usb_submit_urb(read urb) failed" ); - -} - - -static int digi_setbaud( struct usb_serial_port *port, int baud ) -{ - - int bindex; - - -dbg( "digi_setbaud: TOP: port=%d", port->number ); - - switch( baud ) { - case 50: bindex = DIGI_BAUD_50; break; - case 75: bindex = DIGI_BAUD_75; break; - case 110: bindex = DIGI_BAUD_110; break; - case 150: bindex = DIGI_BAUD_150; break; - case 200: bindex = DIGI_BAUD_200; break; - case 300: bindex = DIGI_BAUD_300; break; - case 600: bindex = DIGI_BAUD_600; break; - case 1200: bindex = DIGI_BAUD_1200; break; - case 1800: bindex = DIGI_BAUD_1800; break; - case 2400: bindex = DIGI_BAUD_2400; break; - case 4800: bindex = DIGI_BAUD_4800; break; - case 7200: bindex = DIGI_BAUD_7200; break; - case 9600: bindex = DIGI_BAUD_9600; break; - case 14400: bindex = DIGI_BAUD_14400; break; - case 19200: bindex = DIGI_BAUD_19200; break; - case 28800: bindex = DIGI_BAUD_28800; break; - case 38400: bindex = DIGI_BAUD_38400; break; - case 57600: bindex = DIGI_BAUD_57600; break; - case 76800: bindex = DIGI_BAUD_76800; break; - case 115200: bindex = DIGI_BAUD_115200; break; - case 153600: bindex = DIGI_BAUD_153600; break; - case 230400: bindex = DIGI_BAUD_230400; break; - case 460800: bindex = DIGI_BAUD_460800; break; - default: - dbg( "digi_setbaud: can't handle requested baud rate %d", baud ); - return( -EINVAL ); - break; - } - - digi_send_cmd( "digi_setbaud:", port, DIGI_CMD_SET_BAUD_RATE, 2, bindex ); - - return( 0 ); /* FIX -- send_cmd should return a value??, return it */ + // dbg( "digi_rx_unthrottle: usb_submit_urb failed" ); } @@ -367,167 +455,243 @@ { unsigned int iflag = port->tty->termios->c_iflag; - unsigned int old_iflag = old_termios->c_iflag; unsigned int cflag = port->tty->termios->c_cflag; + unsigned int old_iflag = old_termios->c_iflag; unsigned int old_cflag = old_termios->c_cflag; - int arg; + unsigned char buf[32]; + int arg,ret; + int i = 0; dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", port->number, iflag, old_iflag, cflag, old_cflag ); /* set baud rate */ - /* if( (cflag&CBAUD) != (old_cflag&CBAUD) ) */ { + if( (cflag&CBAUD) != (old_cflag&CBAUD) ) { + + arg = -1; + + /* reassert DTR and (maybe) RTS on transition from B0 */ + if( (old_cflag&CBAUD) == B0 ) { + /* don't set RTS if using hardware flow control */ + /* and throttling input -- not implemented yet */ + digi_set_modem_signals( port, TIOCM_DTR|TIOCM_RTS ); + } + switch( (cflag&CBAUD) ) { - case B50: digi_setbaud(port, 50); break; - case B75: digi_setbaud(port, 75); break; - case B110: digi_setbaud(port, 110); break; - case B150: digi_setbaud(port, 150); break; - case B200: digi_setbaud(port, 200); break; - case B300: digi_setbaud(port, 300); break; - case B600: digi_setbaud(port, 600); break; - case B1200: digi_setbaud(port, 1200); break; - case B1800: digi_setbaud(port, 1800); break; - case B2400: digi_setbaud(port, 2400); break; - case B4800: digi_setbaud(port, 4800); break; - case B9600: digi_setbaud(port, 9600); break; - case B19200: digi_setbaud(port, 19200); break; - case B38400: digi_setbaud(port, 38400); break; - case B57600: digi_setbaud(port, 57600); break; - case B115200: digi_setbaud(port, 115200); break; - default: - dbg( "digi_set_termios: can't handle baud rate 0x%x", - (cflag&CBAUD) ); - break; + /* drop DTR and RTS on transition to B0 */ + case B0: digi_set_modem_signals( port, 0 ); break; + case B50: arg = DIGI_BAUD_50; break; + case B75: arg = DIGI_BAUD_75; break; + case B110: arg = DIGI_BAUD_110; break; + case B150: arg = DIGI_BAUD_150; break; + case B200: arg = DIGI_BAUD_200; break; + case B300: arg = DIGI_BAUD_300; break; + case B600: arg = DIGI_BAUD_600; break; + case B1200: arg = DIGI_BAUD_1200; break; + case B1800: arg = DIGI_BAUD_1800; break; + case B2400: arg = DIGI_BAUD_2400; break; + case B4800: arg = DIGI_BAUD_4800; break; + case B9600: arg = DIGI_BAUD_9600; break; + case B19200: arg = DIGI_BAUD_19200; break; + case B38400: arg = DIGI_BAUD_38400; break; + case B57600: arg = DIGI_BAUD_57600; break; + case B115200: arg = DIGI_BAUD_115200; break; + case B230400: arg = DIGI_BAUD_230400; break; + case B460800: arg = DIGI_BAUD_460800; break; + default: + dbg( "digi_set_termios: can't handle baud rate 0x%x", + (cflag&CBAUD) ); + break; } + + if( arg != -1 ) { + buf[i++] = DIGI_CMD_SET_BAUD_RATE; + buf[i++] = port->number; + buf[i++] = arg; + buf[i++] = 0; + } + + } + + /* set parity */ + if( (cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD)) ) { + + if( (cflag&PARENB) ) { + if( (cflag&PARODD) ) + arg = DIGI_PARITY_ODD; + else + arg = DIGI_PARITY_EVEN; + } else { + arg = DIGI_PARITY_NONE; + } + + buf[i++] = DIGI_CMD_SET_PARITY; + buf[i++] = port->number; + buf[i++] = arg; + buf[i++] = 0; + + } + + /* set word size */ + if( (cflag&CSIZE) != (old_cflag&CSIZE) ) { + + arg = -1; + + switch( (cflag&CSIZE) ) { + case CS5: arg = DIGI_WORD_SIZE_5; break; + case CS6: arg = DIGI_WORD_SIZE_6; break; + case CS7: arg = DIGI_WORD_SIZE_7; break; + case CS8: arg = DIGI_WORD_SIZE_8; break; + default: + dbg( "digi_set_termios: can't handle word size %d", + (cflag&CSIZE) ); + break; + } + + if( arg != -1 ) { + buf[i++] = DIGI_CMD_SET_WORD_SIZE; + buf[i++] = port->number; + buf[i++] = arg; + buf[i++] = 0; + } + + } + + /* set stop bits */ + if( (cflag&CSTOPB) != (old_cflag&CSTOPB) ) { + + if( (cflag&CSTOPB) ) + arg = DIGI_STOP_BITS_2; + else + arg = DIGI_STOP_BITS_1; + + buf[i++] = DIGI_CMD_SET_STOP_BITS; + buf[i++] = port->number; + buf[i++] = arg; + buf[i++] = 0; + } /* set input flow control */ - /* if( (iflag&IXOFF) != (old_iflag&IXOFF) - || (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) */ { + if( (iflag&IXOFF) != (old_iflag&IXOFF) + || (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) { arg = 0; if( (iflag&IXOFF) ) - arg |= DIGI_ENABLE_IXON_IXOFF_FLOW_CONTROL; + arg |= DIGI_INPUT_FLOW_CONTROL_XON_XOFF; + else + arg &= ~DIGI_INPUT_FLOW_CONTROL_XON_XOFF; + if( (cflag&CRTSCTS) ) - arg |= DIGI_ENABLE_RTS_CTS_FLOW_CONTROL; + arg |= DIGI_INPUT_FLOW_CONTROL_RTS; + else + arg &= ~DIGI_INPUT_FLOW_CONTROL_RTS; - digi_send_cmd( "digi_termios: set input flow control:", port, - DIGI_CMD_SET_INPUT_FLOW_CONTROL, 2, arg ); + buf[i++] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; + buf[i++] = port->number; + buf[i++] = arg; + buf[i++] = 0; } /* set output flow control */ - /* if( (iflag&IXON) != (old_iflag&IXON) - || (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) */ { + /*if( (iflag&IXON) != (old_iflag&IXON) + || (cflag&CRTSCTS) != (old_cflag&CRTSCTS) )*/ { arg = 0; if( (iflag&IXON) ) - arg |= DIGI_ENABLE_IXON_IXOFF_FLOW_CONTROL; + arg |= DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF; + else + arg &= ~DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF; + if( (cflag&CRTSCTS) ) - arg |= DIGI_ENABLE_RTS_CTS_FLOW_CONTROL; + arg |= DIGI_OUTPUT_FLOW_CONTROL_CTS; + else + arg &= ~DIGI_OUTPUT_FLOW_CONTROL_CTS; - digi_send_cmd( "digi_set_termios: set output flow control:", port, - DIGI_CMD_SET_OUTPUT_FLOW_CONTROL, 2, arg ); + buf[i++] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL; + buf[i++] = port->number; + buf[i++] = arg; + buf[i++] = 0; } -} + /* set receive enable/disable */ + if( (cflag&CREAD) != (old_cflag&CREAD) ) { + if( (cflag&CREAD) ) + arg = DIGI_ENABLE; + else + arg = DIGI_DISABLE; -static void digi_break_ctl( struct usb_serial_port *port, int break_state ) -{ -dbg( "digi_break_ctl: TOP: port=%d", port->number ); -} + buf[i++] = DIGI_CMD_RECEIVE_ENABLE; + buf[i++] = port->number; + buf[i++] = arg; + buf[i++] = 0; + } -/* modem control pins: DTR and RTS are outputs and can be controlled; - DCD, RI, DSR, CTS are inputs and can be read */ + if( (ret=digi_write_oob( buf, i )) != 0 ) + dbg( "digi_set_termios: write oob failed, ret=%d", ret ); -static int digi_get_modem_info( struct usb_serial *serial, - unsigned char *value ) -{ -dbg( "digi_get_modem_info: TOP" ); - return( 0 ); } -static int digi_set_modem_info( struct usb_serial *serial, - unsigned char value ) +static void digi_break_ctl( struct usb_serial_port *port, int break_state ) { -dbg( "digi_set_modem_info: TOP" ); - return( 0 ); +dbg( "digi_break_ctl: TOP: port=%d", port->number ); } static int digi_ioctl( struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg ) { - struct usb_serial *serial = port->serial; - int rc; - unsigned int value; - unsigned char status, mask; + + digi_private_t *priv = (digi_private_t *)(port->private); + unsigned int val; + dbg( "digi_ioctl: TOP: port=%d, cmd=0x%x", port->number, cmd ); -return( -ENOIOCTLCMD ); switch (cmd) { - case TIOCMGET: /* get modem pins state */ - rc = digi_get_modem_info(serial, &status); - if (rc < 0) - return rc; - value = - ((status & (1<<7)) ? TIOCM_DTR : 0) | - ((status & (1<<6)) ? TIOCM_CAR : 0) | - ((status & (1<<5)) ? TIOCM_RNG : 0) | - ((status & (1<<4)) ? TIOCM_DSR : 0) | - ((status & (1<<3)) ? TIOCM_CTS : 0) | - ((status & (1<<2)) ? TIOCM_RTS : 0); - if (copy_to_user((unsigned int *)arg, &value, sizeof(int))) - return -EFAULT; - return 0; - case TIOCMSET: /* set a state as returned by MGET */ - if (copy_from_user(&value, (unsigned int *)arg, sizeof(int))) - return -EFAULT; - status = - ((value & TIOCM_DTR) ? (1<<7) : 0) | - ((value & TIOCM_CAR) ? (1<<6) : 0) | - ((value & TIOCM_RNG) ? (1<<5) : 0) | - ((value & TIOCM_DSR) ? (1<<4) : 0) | - ((value & TIOCM_CTS) ? (1<<3) : 0) | - ((value & TIOCM_RTS) ? (1<<2) : 0); - rc = digi_set_modem_info(serial, status); - if (rc < 0) - return rc; - return 0; - case TIOCMBIS: /* set bits in bitmask */ - case TIOCMBIC: /* clear bits from bitmask */ - if (copy_from_user(&value, (unsigned int *)arg, sizeof(int))) - return -EFAULT; - rc = digi_get_modem_info(serial, &status); - if (rc < 0) - return rc; - mask = - ((value & TIOCM_RTS) ? (1<<2) : 0) | - ((value & TIOCM_DTR) ? (1<<7) : 0); - if (cmd == TIOCMBIS) - status |= mask; - else - status &= ~mask; - rc = digi_set_modem_info(serial, status); - if (rc < 0) - return rc; - return 0; + + case TIOCMGET: + spin_lock( &priv->dp_port_lock ); + val = priv->dp_modem_signals; + spin_unlock( &priv->dp_port_lock ); + if( copy_to_user((unsigned int *)arg, &val, sizeof(int)) ) + return( -EFAULT ); + return( 0 ); + + case TIOCMSET: + case TIOCMBIS: + case TIOCMBIC: + if( copy_from_user(&val, (unsigned int *)arg, sizeof(int)) ) + return( -EFAULT ); + spin_lock( &priv->dp_port_lock ); + if( cmd == TIOCMBIS ) + val = priv->dp_modem_signals | val; + else if( cmd == TIOCMBIC ) + val = priv->dp_modem_signals & ~val; + spin_unlock( &priv->dp_port_lock ); + return( digi_set_modem_signals( port, val ) ); + case TIOCMIWAIT: /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ /* TODO */ + return( 0 ); + case TIOCGICOUNT: /* return count of modemline transitions */ - return 0; /* TODO */ + /* TODO */ + return 0; + } - - return -ENOIOCTLCMD; + + return( -ENOIOCTLCMD ); + } @@ -535,7 +699,7 @@ const unsigned char *buf, int count ) { - int i,ret,data_len,new_len; + int ret,data_len,new_len; digi_private_t *priv = (digi_private_t *)(port->private); @@ -550,16 +714,18 @@ /* wait for urb status clear to submit another urb */ if( port->write_urb->status == -EINPROGRESS ) { -dbg( "digi_write: -EINPROGRESS set" ); - - /* buffer the data if possible */ - new_len = MIN( count, DIGI_PORT_BUF_LEN-priv->dp_buf_len ); - memcpy( priv->dp_buf+priv->dp_buf_len, buf, new_len ); - priv->dp_buf_len += new_len; + /* buffer data if count is 1 (probably put_char) if possible */ + if( count == 1 ) { + new_len = MIN( count, + DIGI_PORT_BUF_LEN-priv->dp_buf_len ); + memcpy( priv->dp_buf+priv->dp_buf_len, buf, new_len ); + priv->dp_buf_len += new_len; + } else { + new_len = 0; + } - /* unlock and return number of bytes buffered */ spin_unlock( &priv->dp_port_lock ); -dbg( "digi_write: buffering, return %d", new_len ); + return( new_len ); } @@ -569,19 +735,16 @@ new_len = MIN( count, port->bulk_out_size-2-priv->dp_buf_len ); data_len = new_len + priv->dp_buf_len; -dbg( "digi_write: counts: new data %d, buf data %d, total data %d (max %d)", new_len, priv->dp_buf_len, data_len, port->bulk_out_size-2 ); - - /* nothing to send */ if( data_len == 0 ) { spin_unlock( &priv->dp_port_lock ); return( 0 ); } - /* set command and length bytes */ - *((u8 *)(port->write_urb->transfer_buffer)) = (u8)DIGI_CMD_SEND_DATA; - *((u8 *)(port->write_urb->transfer_buffer)+1) = (u8)data_len; + *((unsigned char *)(port->write_urb->transfer_buffer)) + = (unsigned char)DIGI_CMD_SEND_DATA; + *((unsigned char *)(port->write_urb->transfer_buffer)+1) + = (unsigned char)data_len; - /* set total transfer buffer length */ port->write_urb->transfer_buffer_length = data_len+2; /* copy in buffered data first */ @@ -590,33 +753,34 @@ /* copy in new data */ if( from_user ) { - copy_from_user( port->write_urb->transfer_buffer+2+priv->dp_buf_len, + copy_from_user( + port->write_urb->transfer_buffer+2+priv->dp_buf_len, buf, new_len ); - } - else { + } else { memcpy( port->write_urb->transfer_buffer+2+priv->dp_buf_len, buf, new_len ); } -#ifdef DEBUG - printk( KERN_DEBUG __FILE__ ": digi_write: length=%d, data=", - port->write_urb->transfer_buffer_length ); +#ifdef DEBUG_DATA +{ + int i; + + printk( KERN_DEBUG __FILE__ ": digi_write: port=%d, length=%d, data=", + port->number, port->write_urb->transfer_buffer_length ); for( i=0; iwrite_urb->transfer_buffer_length; ++i ) { printk( "%.2x ", - ((unsigned char *)port->write_urb->transfer_buffer)[i] ); + ((unsigned char *)port->write_urb->transfer_buffer)[i] ); } printk( "\n" ); +} #endif - /* submit urb */ if( (ret=usb_submit_urb(port->write_urb)) == 0 ) { - /* submit successful, return length of new data written */ ret = new_len; - /* clear buffer */ priv->dp_buf_len = 0; - } - else { - dbg( "digi_write: usb_submit_urb(write bulk) failed, ret=%d", ret ); + } else { + dbg( "digi_write: usb_submit_urb failed, ret=%d", + ret ); /* no bytes written - should we return the error code or 0? */ ret = 0; } @@ -658,28 +822,34 @@ spin_lock( &priv->dp_port_lock ); if( port->write_urb->status != -EINPROGRESS && priv->dp_buf_len > 0 ) { - /* set command and length bytes */ - *((u8 *)(port->write_urb->transfer_buffer)) - = (u8)DIGI_CMD_SEND_DATA; - *((u8 *)(port->write_urb->transfer_buffer)+1) - = (u8)priv->dp_buf_len; + *((unsigned char *)(port->write_urb->transfer_buffer)) + = (unsigned char)DIGI_CMD_SEND_DATA; + *((unsigned char *)(port->write_urb->transfer_buffer)+1) + = (unsigned char)priv->dp_buf_len; - /* set total transfer buffer length */ port->write_urb->transfer_buffer_length = priv->dp_buf_len+2; - /* copy in buffered data */ memcpy( port->write_urb->transfer_buffer+2, priv->dp_buf, priv->dp_buf_len ); - /* submit urb */ -dbg( "digi_write_bulk_callback: submit urb to write buffer, data len=%d", -priv->dp_buf_len ); +#ifdef DEBUG_DATA +{ + int i; + + printk( KERN_DEBUG __FILE__ ": digi_write_bulk_callback: port=%d, length=%d, data=", + port->number, port->write_urb->transfer_buffer_length ); + for( i=0; iwrite_urb->transfer_buffer_length; ++i ) { + printk( "%.2x ", + ((unsigned char *)port->write_urb->transfer_buffer)[i] ); + } + printk( "\n" ); +} +#endif + if( (ret=usb_submit_urb(port->write_urb)) == 0 ) { - /* successful, clear buffer */ priv->dp_buf_len = 0; - } - else { - dbg( "digi_write_bulk_callback: usb_submit_urb(write bulk) failed, ret=%d", ret ); + } else { + dbg( "digi_write_bulk_callback: usb_submit_urb failed, ret=%d", ret ); } } @@ -690,7 +860,8 @@ /* wake up line discipline */ tty = port->tty; - if( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup ) + if( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) + && tty->ldisc.write_wakeup ) (tty->ldisc.write_wakeup)(tty); /* wake up other tty processes */ @@ -717,7 +888,7 @@ spin_unlock( &priv->dp_port_lock ); -dbg( "digi_write_room: return room=%d", room ); +dbg( "digi_write_room: port=%d, room=%d", port->number, room ); return( room ); } @@ -732,11 +903,10 @@ dbg( "digi_chars_in_buffer: TOP: port=%d", port->number ); if( port->write_urb->status == -EINPROGRESS ) { -dbg( "digi_chars_in_buffer: return=%d", port->bulk_out_size ); - return( port->bulk_out_size ); - } - else { -dbg( "digi_chars_in_buffer: return=%d", priv->dp_buf_len ); +dbg( "digi_chars_in_buffer: port=%d, chars=%d", port->number, port->bulk_out_size - 2 ); + return( port->bulk_out_size - 2 ); + } else { +dbg( "digi_chars_in_buffer: port=%d, chars=%d", port->number, priv->dp_buf_len ); return( priv->dp_buf_len ); } @@ -746,61 +916,53 @@ static int digi_open( struct usb_serial_port *port, struct file *filp ) { + int i = 0; int ret; + unsigned char buf[32]; digi_private_t *priv = (digi_private_t *)(port->private); + struct termios not_termios; + +dbg( "digi_open: TOP: port %d, active:%d", port->number, port->active ); -dbg( "digi_open: TOP: port %d", port->number ); + /* be sure the device is started up */ + if( digi_startup_device( port->serial ) != 0 ) + return( -ENXIO ); + + MOD_INC_USE_COUNT; /* if port is already open, just return */ - /* be sure exactly one open succeeds */ + /* be sure exactly one open proceeds */ spin_lock( &priv->dp_port_lock ); - if( port->active ) { + if( port->active++ ) { + spin_unlock( &priv->dp_port_lock ); return( 0 ); } - port->active = 1; spin_unlock( &priv->dp_port_lock ); - /* start reading from the out-of-band port for the device */ - /* be sure this happens exactly once */ - spin_lock( &config_lock ); - if( !oob_read_started ) { - if( (ret=usb_submit_urb(oob_port->read_urb)) != 0 ) { - dbg( "digi_open: usb_submit_urb(read bulk) for oob failed, ret=%d", - ret ); - spin_unlock( &config_lock ); - return( -ENXIO ); - } - else { -dbg( "digi_open: usb_submit_urb(read bulk) for oob succeeded" ); - oob_read_started = 1; - } - } - spin_unlock( &config_lock ); - - /* initialize port */ -dbg( "digi_open: init..." ); - /* set 9600, 8N1, DTR, RTS, RX enable, no input or output flow control */ - digi_setbaud( port, 9600 ); - digi_send_cmd( "digi_open: wordsize", port, DIGI_CMD_SET_WORD_SIZE, 2, 3 ); - digi_send_cmd( "digi_open: parity", port, DIGI_CMD_SET_PARITY, 2, 0 ); - digi_send_cmd( "digi_open: stopbits", port, DIGI_CMD_SET_STOP_BITS, 2, 0 ); - digi_send_cmd( "digi_open: DTR on", port, DIGI_CMD_SET_DTR_SIGNAL, 2, 1 ); - digi_send_cmd( "digi_open: RTS on", port, DIGI_CMD_SET_RTS_SIGNAL, 2, 1 ); - digi_send_cmd( "digi_open: RX enable on", port, DIGI_CMD_RECEIVE_ENABLE, 2, - 1 ); - digi_send_cmd( "digi_open: input flow control off", port, - DIGI_CMD_SET_INPUT_FLOW_CONTROL, 2, 0 ); - digi_send_cmd( "digi_open: output flow control off", port, - DIGI_CMD_SET_OUTPUT_FLOW_CONTROL, 2, 0 ); - - /* start reading from the device */ - if( (ret=usb_submit_urb(port->read_urb)) != 0 ) { - dbg( "digi_open: usb_submit_urb(read bulk) failed, ret=%d", ret ); - return( -ENXIO ); - } + /* read modem signals automatically whenever they change */ + buf[i++] = DIGI_CMD_READ_INPUT_SIGNALS; + buf[i++] = port->number; + buf[i++] = DIGI_ENABLE; + buf[i++] = 0; + + /* flush fifos */ + buf[i++] = DIGI_CMD_IFLUSH_FIFO; + buf[i++] = port->number; + buf[i++] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; + buf[i++] = 0; + + if( (ret=digi_write_oob( buf, i )) != 0 ) + dbg( "digi_open: write oob failed, ret=%d", ret ); + + /* set termios settings */ + not_termios.c_cflag = ~port->tty->termios->c_cflag; + not_termios.c_iflag = ~port->tty->termios->c_iflag; + digi_set_termios( port, ¬_termios ); + + /* set DTR and RTS */ + digi_set_modem_signals( port, TIOCM_DTR|TIOCM_RTS ); -dbg( "digi_open: done" ); return( 0 ); } @@ -809,39 +971,119 @@ static void digi_close( struct usb_serial_port *port, struct file *filp ) { -dbg( "digi_close: TOP: port %d", port->number ); + int i = 0; + int ret; + unsigned char buf[32]; + digi_private_t *priv = (digi_private_t *)(port->private); + + +dbg( "digi_close: TOP: port %d, active:%d", port->number, port->active ); + + + /* do cleanup only after final close on this port */ + spin_lock( &priv->dp_port_lock ); + if( --port->active ) { + spin_unlock( &priv->dp_port_lock ); + MOD_DEC_USE_COUNT; + return; + } + spin_unlock( &priv->dp_port_lock ); - /* Need to change the control lines here */ - /* TODO */ -dbg( "digi_close: wanna clear DTR and RTS..." ); - -//digi_send_cmd( "digi_close DTR off", port, 6, 2, 0); // clear DTR -//digi_send_cmd( "digi_close RTS off", port, 7, 2, 0); // clear RTS -//digi_send_cmd( "digi_close RX disable", port, 10, 2, 0); // Rx Disable - -digi_send_oob( "digi_close RTS off", DIGI_CMD_SET_RTS_SIGNAL, - port->number, 0, 0 ); // clear RTS -digi_send_oob( "digi_close DTR off", DIGI_CMD_SET_DTR_SIGNAL, - port->number, 0, 0 ); // clear DTR + /* drop DTR and RTS */ + digi_set_modem_signals( port, 0 ); + /* disable input flow control */ + buf[i++] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; + buf[i++] = port->number; + buf[i++] = DIGI_DISABLE; + buf[i++] = 0; + + /* disable output flow control */ + buf[i++] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL; + buf[i++] = port->number; + buf[i++] = DIGI_DISABLE; + buf[i++] = 0; + + /* disable reading modem signals automatically */ + buf[i++] = DIGI_CMD_READ_INPUT_SIGNALS; + buf[i++] = port->number; + buf[i++] = DIGI_DISABLE; + buf[i++] = 0; + + /* flush fifos */ + buf[i++] = DIGI_CMD_IFLUSH_FIFO; + buf[i++] = port->number; + buf[i++] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; + buf[i++] = 0; + + /* disable receive */ + buf[i++] = DIGI_CMD_RECEIVE_ENABLE; + buf[i++] = port->number; + buf[i++] = DIGI_DISABLE; + buf[i++] = 0; + + if( (ret=digi_write_oob( buf, i )) != 0 ) + dbg( "digi_close: write oob failed, ret=%d", ret ); + + /* wait for final commands on oob port to complete */ while( oob_port->write_urb->status == -EINPROGRESS ) { -dbg ("digi_close: waiting for final writes to complete on oob port %d...", oob_port->number ); - interruptible_sleep_on( &oob_port->write_wait ); + interruptible_sleep_on_timeout( &oob_port->write_wait, + DIGI_RETRY_TIMEOUT ); if( signal_pending(current) ) { break; } } - /* shutdown our bulk reads and writes */ + /* shutdown any outstanding bulk writes */ usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->read_urb); - port->active = 0; + MOD_DEC_USE_COUNT; } -static int digi_startup (struct usb_serial *serial) +/* +* Digi Startup Device +* +* Starts reads on all ports. Must be called AFTER startup, with +* urbs initialized. Returns 0 if successful, non-zero error otherwise. +*/ + +static int digi_startup_device( struct usb_serial *serial ) +{ + + int i,ret = 0; + + + spin_lock( &startup_lock ); + + /* be sure this happens exactly once */ + if( device_startup ) { + spin_unlock( &startup_lock ); + return( 0 ); + } + + /* start reading from each bulk in endpoint for the device */ + for( i=0; iport[i].read_urb)) != 0 ) { + dbg( "digi_startup_device: usb_submit_urb failed, port=%d, ret=%d", + i, ret ); + break; + } + + } + + device_startup = 1; + + spin_unlock( &startup_lock ); + + return( ret ); + +} + + +static int digi_startup( struct usb_serial *serial ) { int i; @@ -850,22 +1092,24 @@ dbg( "digi_startup: TOP" ); - /* initialize config lock */ - spin_lock_init( &config_lock ); + spin_lock_init( &startup_lock ); /* allocate the private data structures for all ports */ /* number of regular ports + 1 for the out-of-band port */ for( i=0; iport[i].active = 0; + /* allocate private structure */ priv = serial->port[i].private = - (digi_private_t *)kmalloc( sizeof(struct digi_private), + (digi_private_t *)kmalloc( sizeof(digi_private_t), GFP_KERNEL ); if( priv == (digi_private_t *)0 ) - return( 1 ); /* error */ + return( 1 ); /* error */ /* initialize private structure */ priv->dp_buf_len = 0; + priv->dp_modem_signals = 0; spin_lock_init( &priv->dp_port_lock ); /* initialize write wait queue for this port */ @@ -876,7 +1120,7 @@ /* initialize out of band port info */ oob_port_num = digi_acceleport_device.num_ports; oob_port = &serial->port[oob_port_num]; - oob_read_started = 0; + device_startup = 0; return( 0 ); @@ -891,10 +1135,13 @@ dbg( "digi_shutdown: TOP" ); - /* stop writing and reading from the out-of-band port */ - usb_unlink_urb( oob_port->write_urb ); - usb_unlink_urb( oob_port->read_urb ); - oob_read_started = 0; + /* stop reads and writes on all ports */ + for( i=0; iport[i].read_urb); + usb_unlink_urb (serial->port[i].write_urb); + } + + device_startup = 0; /* free the private data structures for all ports */ /* number of regular ports + 1 for the out-of-band port */ @@ -910,7 +1157,10 @@ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial *serial = port->serial; struct tty_struct *tty = port->tty; - unsigned char *data = urb->transfer_buffer; + int opcode = ((unsigned char *)urb->transfer_buffer)[0]; + int len = ((unsigned char *)urb->transfer_buffer)[1]; + int status = ((unsigned char *)urb->transfer_buffer)[2]; + unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3; int ret,i; @@ -918,58 +1168,108 @@ /* handle oob callback */ if( port->number == oob_port_num ) { -dbg( "digi_read_bulk_callback: oob_port callback, opcode=%d, line=%d, status=%d, ret=%d", data[0], data[1], data[2], data[3] ); - if( urb->status ) { - dbg( "digi_read_bulk_callback: nonzero read bulk status on oob: %d", - urb->status ); - } - if( (ret=usb_submit_urb(urb)) != 0 ) { - dbg( "digi_read_bulk_callback: failed resubmitting oob urb, ret=%d", - ret ); - } + digi_read_oob( urb ); return; } /* sanity checks */ if( port_paranoia_check( port, "digi_read_bulk_callback" ) || serial_paranoia_check( serial, "digi_read_bulk_callback" ) ) { - return; + goto resubmit; } - /* check status */ if( urb->status ) { dbg( "digi_read_bulk_callback: nonzero read bulk status: %d", urb->status ); - return; + goto resubmit; } -#ifdef DEBUG - if (urb->actual_length) { - printk( KERN_DEBUG __FILE__ ": digi_read_bulk_callback: length=%d, data=", - urb->actual_length ); - for( i=0; iactual_length; ++i ) { - printk( "%.2x ", data[i] ); - } - printk( "\n" ); +#ifdef DEBUG_DATA +if( urb->actual_length ) { + printk( KERN_DEBUG __FILE__ ": digi_read_bulk_callback: port=%d, length=%d, data=", + port->number, urb->actual_length ); + for( i=0; iactual_length; ++i ) { + printk( "%.2x ", ((unsigned char *)urb->transfer_buffer)[i] ); } + printk( "\n" ); +} #endif - /* Digi read packets are: */ - /* 0 1 2 3 4 ... 3+length-1 == 2+length*/ - /* opcode, length, status, data[0], data[1]...data[length-2] */ - if( urb->actual_length > 3 ) { - for( i=3; i<2+data[1]; ++i ) { + if( urb->actual_length != len + 2 ) + err( KERN_INFO "digi_read_bulk_callback: INCOMPLETE PACKET, port=%d, opcode=%d, len=%d, actual_length=%d, status=%d", port->number, opcode, len, urb->actual_length, status ); + + /* receive data */ + if( opcode == DIGI_CMD_RECEIVE_DATA && urb->actual_length > 3 ) { + len = MIN( len, urb->actual_length-3 ); + for( i=0; icontext; + struct usb_serial *serial = port->serial; + digi_private_t *priv; + int oob_opcode = ((unsigned char *)urb->transfer_buffer)[0]; + int oob_line = ((unsigned char *)urb->transfer_buffer)[1]; + int oob_status = ((unsigned char *)urb->transfer_buffer)[2]; + int oob_ret = ((unsigned char *)urb->transfer_buffer)[3]; + int ret; + + +dbg( "digi_read_oob: opcode=%d, line=%d, status=%d, ret=%d", oob_opcode, oob_line, oob_status, oob_ret ); + + if( urb->status ) { + dbg( "digi_read_oob: nonzero read bulk status on oob: %d", + urb->status ); + goto resubmit; + } + + if( oob_opcode == DIGI_CMD_READ_INPUT_SIGNALS && oob_status == 0 ) { + + priv = serial->port[oob_line].private; + + spin_lock( &priv->dp_port_lock ); + + /* convert from digi flags to termiox flags */ + if( oob_ret & DIGI_READ_INPUT_SIGNALS_CTS ) + priv->dp_modem_signals |= TIOCM_CTS; + else + priv->dp_modem_signals &= ~TIOCM_CTS; + if( oob_ret & DIGI_READ_INPUT_SIGNALS_DSR ) + priv->dp_modem_signals |= TIOCM_DSR; + else + priv->dp_modem_signals &= ~TIOCM_DSR; + if( oob_ret & DIGI_READ_INPUT_SIGNALS_RI ) + priv->dp_modem_signals |= TIOCM_RI; + else + priv->dp_modem_signals &= ~TIOCM_RI; + if( oob_ret & DIGI_READ_INPUT_SIGNALS_DCD ) + priv->dp_modem_signals |= TIOCM_CD; + else + priv->dp_modem_signals &= ~TIOCM_CD; + + spin_unlock( &priv->dp_port_lock ); + + } + +resubmit: + if( (ret=usb_submit_urb(urb)) != 0 ) { + dbg( "digi_read_oob: failed resubmitting oob urb, ret=%d", + ret ); + } + +} diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c --- v2.3.99-pre8/linux/drivers/usb/serial/ftdi_sio.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/serial/ftdi_sio.c Tue May 23 08:21:51 2000 @@ -32,9 +32,6 @@ #include - -#ifdef CONFIG_USB_SERIAL_FTDI_SIO - #include #include #include @@ -722,7 +719,4 @@ dbg("ftdi_sio_ioctl returning 0"); return 0; } /* ftdi_sio_ioctl */ - -#endif /* CONFIG_USB_SERIAL_FTDI_SIO */ - diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/keyspan_pda.c linux/drivers/usb/serial/keyspan_pda.c --- v2.3.99-pre8/linux/drivers/usb/serial/keyspan_pda.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/serial/keyspan_pda.c Tue May 23 08:21:51 2000 @@ -18,9 +18,6 @@ #include - -#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA - #include #include #include @@ -700,4 +697,3 @@ shutdown: keyspan_pda_shutdown, }; -#endif /* CONFIG_USB_SERIAL_KEYSPAN_PDA */ diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/omninet.c linux/drivers/usb/serial/omninet.c --- v2.3.99-pre8/linux/drivers/usb/serial/omninet.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/serial/omninet.c Tue May 23 08:21:51 2000 @@ -13,9 +13,6 @@ */ #include - -#ifdef CONFIG_USB_SERIAL_OMNINET - #include #include #include @@ -335,7 +332,4 @@ return; } - -#endif /* CONFIG_USB_SERIAL_OMNINET */ - diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c --- v2.3.99-pre8/linux/drivers/usb/serial/usbserial.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/serial/usbserial.c Tue May 23 08:21:51 2000 @@ -14,6 +14,10 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (05/22/2000) gkh + * Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be + * removed from the individual device source files. + * * (05/03/2000) gkh * Added the Digi Acceleport driver from Al Borchers and Peter Berger. * diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c --- v2.3.99-pre8/linux/drivers/usb/serial/visor.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/serial/visor.c Tue May 23 08:21:51 2000 @@ -20,9 +20,6 @@ */ #include - -#ifdef CONFIG_USB_SERIAL_VISOR - #include #include #include @@ -206,8 +203,4 @@ /* continue on with initialization */ return (0); } - - -#endif /* CONFIG_USB_SERIAL_VISOR*/ - diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/whiteheat.c linux/drivers/usb/serial/whiteheat.c --- v2.3.99-pre8/linux/drivers/usb/serial/whiteheat.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/serial/whiteheat.c Tue May 23 08:21:51 2000 @@ -21,9 +21,6 @@ */ #include - -#ifdef CONFIG_USB_SERIAL_WHITEHEAT - #include #include #include @@ -406,7 +403,4 @@ return; } - -#endif /* CONFIG_USB_SERIAL_WHITEHEAT */ - diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c --- v2.3.99-pre8/linux/drivers/usb/uhci.c Fri May 12 14:18:55 2000 +++ linux/drivers/usb/uhci.c Sat May 20 11:39:27 2000 @@ -821,6 +821,7 @@ /* Control status phase */ status = uhci_status_bits(td->status); +#ifdef I_HAVE_BUGGY_APC_BACKUPS /* APC BackUPS Pro kludge */ /* It tries to send all of the descriptor instead of the amount */ /* we requested */ @@ -828,6 +829,7 @@ status & TD_CTRL_ACTIVE && status & TD_CTRL_NAK) return 0; +#endif if (status & TD_CTRL_ACTIVE) return -EINPROGRESS; @@ -2325,30 +2327,29 @@ { int i; + /* disable legacy emulation */ + pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT); + + if (pci_enable_device(dev) < 0) + return -1; + + if (!dev->irq) { + err("found UHCI device with no IRQ assigned. check BIOS settings!"); + return -1; + } + /* Search for the IO base address.. */ for (i = 0; i < 6; i++) { - unsigned int io_addr = dev->resource[i].start; - unsigned int io_size = - dev->resource[i].end - dev->resource[i].start + 1; + unsigned int io_addr = pci_resource_start(dev, i); + unsigned int io_size = pci_resource_len(dev, i); /* IO address? */ - if (!(dev->resource[i].flags & IORESOURCE_IO)) + if (!(pci_resource_flags(dev, i) & IORESOURCE_IO)) continue; /* Is it already in use? */ if (check_region(io_addr, io_size)) break; - - if (!dev->irq) { - err("found UHCI device with no IRQ assigned. check BIOS settings!"); - continue; - } - - /* disable legacy emulation */ - pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT); - - if (pci_enable_device(dev) < 0) - continue; return setup_uhci(dev, dev->irq, io_addr, io_size); } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c --- v2.3.99-pre8/linux/drivers/usb/usb-ohci.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/usb-ohci.c Tue May 23 08:22:07 2000 @@ -92,7 +92,6 @@ kfree (urb->hcpriv); urb->hcpriv = NULL; - wake_up (&op_wakeup); } /*-------------------------------------------------------------------------*/ @@ -493,16 +492,16 @@ urb->start_frame = ((ed->state == ED_OPER)? (ed->last_iso + 1): (le16_to_cpu (ohci->hcca.frame_no) + 10)) & 0xffff; } + urb->status = USB_ST_URB_PENDING; + urb->actual_length = 0; if (ed->state != ED_OPER) /* link the ed into a chain if is not already */ ep_link (ohci, ed); + urb->status = USB_ST_URB_PENDING; td_submit_urb (urb); /* fill the TDs and link it to the ed */ spin_unlock_irqrestore (&usb_ed_lock, flags); - - urb->status = USB_ST_URB_PENDING; - // queue_urb(s, &urb->urb_list); return 0; } @@ -529,6 +528,8 @@ urb_print (urb, "UNLINK", 1); #endif + usb_dec_dev_use (urb->dev); + if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) return rh_unlink_urb (urb); /* a request to the virtual root hub */ @@ -546,19 +547,23 @@ ep_rm_ed (urb->dev, urb_priv->ed); urb_priv->ed->state |= ED_URB_DEL; spin_unlock_irqrestore (&usb_ed_lock, flags); - - add_wait_queue (&op_wakeup, &wait); - current->state = TASK_UNINTERRUPTIBLE; - if (!schedule_timeout (HZ / 10)) /* wait until all TDs are deleted */ - err("unlink URB timeout!"); - remove_wait_queue (&op_wakeup, &wait); - } else + if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) { + add_wait_queue (&op_wakeup, &wait); + current->state = TASK_UNINTERRUPTIBLE; + if (!schedule_timeout (HZ / 10)) /* wait until all TDs are deleted */ + err("unlink URB timeout!"); + remove_wait_queue (&op_wakeup, &wait); + urb->status = -ENOENT; + } else + urb->status = -EINPROGRESS; + } else { urb_rm_priv (urb); - - urb->status = -ENOENT; // mark urb as killed - if (urb->complete) - urb->complete ((struct urb *) urb); - usb_dec_dev_use (urb->dev); + if (urb->complete && (urb->transfer_flags & USB_ASYNC_UNLINK)) { + urb->complete (urb); + urb->status = 0; + } else + urb->status = -ENOENT; + } } return 0; } @@ -967,7 +972,7 @@ /* prepare a TD */ -static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int type, int index) +static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int index) { volatile td_t * td, * td_pt; urb_priv_t * urb_priv = urb->hcpriv; @@ -984,7 +989,6 @@ td->index = index; td->urb = urb; td->hwINFO = cpu_to_le32 (info); - td->type = type; if ((td->ed->type & 3) == PIPE_ISOCHRONOUS) { td->hwCBP = cpu_to_le32 (((!data || !len)? 0 : virt_to_bus (data)) & 0xFFFFF000); @@ -1031,12 +1035,12 @@ info = usb_pipeout (urb->pipe)? TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; while(data_len > 4096) { - td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, 4096, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt); + td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, 4096, urb, cnt); data += 4096; data_len -= 4096; cnt++; } info = usb_pipeout (urb->pipe)? TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; - td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt); + td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, cnt); cnt++; writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ break; @@ -1044,20 +1048,20 @@ case PIPE_INTERRUPT: info = usb_pipeout (urb->pipe)? TD_CC | TD_DP_OUT | toggle: TD_CC | TD_R | TD_DP_IN | toggle; - td_fill (info, data, data_len, urb, ST_ADDR | ADD_LEN, cnt++); + td_fill (info, data, data_len, urb, cnt++); break; case PIPE_CONTROL: info = TD_CC | TD_DP_SETUP | TD_T_DATA0; - td_fill (info, ctrl, 8, urb, ST_ADDR, cnt++); + td_fill (info, ctrl, 8, urb, cnt++); if (data_len > 0) { info = usb_pipeout (urb->pipe)? TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; - td_fill (info, data, data_len, urb, ADD_LEN, cnt++); + td_fill (info, data, data_len, urb, cnt++); } info = usb_pipeout (urb->pipe)? TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; - td_fill (info, NULL, 0, urb, 0, cnt++); + td_fill (info, NULL, 0, urb, cnt++); writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ break; @@ -1065,7 +1069,7 @@ for (cnt = 0; cnt < urb->number_of_packets; cnt++) { td_fill (TD_CC|TD_ISO | ((urb->start_frame + cnt) & 0xffff), (__u8 *) data + urb->iso_frame_desc[cnt].offset, - urb->iso_frame_desc[cnt].length, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt); + urb->iso_frame_desc[cnt].length, urb, cnt); } break; } @@ -1076,7 +1080,55 @@ /*-------------------------------------------------------------------------* * Done List handling functions *-------------------------------------------------------------------------*/ - + + +/* calculate the transfer length and update the urb */ + +static void dl_transfer_length(td_t * td) +{ + __u32 tdINFO, tdBE, tdCBP; + __u16 tdPSW; + urb_t * urb = td->urb; + urb_priv_t * urb_priv = urb->hcpriv; + int dlen = 0; + int cc = 0; + + tdINFO = le32_to_cpup (&td->hwINFO); + tdBE = le32_to_cpup (&td->hwBE); + tdCBP = le32_to_cpup (&td->hwCBP); + + + if (tdINFO & TD_ISO) { + tdPSW = le16_to_cpu (td->hwPSW[0]); + cc = (tdPSW >> 12) & 0xF; + if (cc < 0xE) { + if (usb_pipeout(urb->pipe)) { + dlen = urb->iso_frame_desc[td->index].length; + } else { + dlen = tdPSW & 0x3ff; + } + urb->actual_length += dlen; + urb->iso_frame_desc[td->index].actual_length = dlen; + if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN)) + cc = TD_CC_NOERROR; + + urb->iso_frame_desc[td->index].status = cc_to_error[cc]; + } + } else { /* BULK, INT, CONTROL DATA */ + if (!(usb_pipetype (urb->pipe) == PIPE_CONTROL && + ((td->index == 0) || (td->index == urb_priv->length - 1)))) { + if (tdBE != 0) { + if (td->hwCBP == 0) + urb->actual_length = bus_to_virt (tdBE) - urb->transfer_buffer + 1; + else + urb->actual_length = bus_to_virt (tdCBP) - urb->transfer_buffer; + } + } + } +} + +/*-------------------------------------------------------------------------*/ + /* replies to the request have to be on a FIFO basis so * we reverse the reversed done-list */ @@ -1130,6 +1182,7 @@ unsigned long flags; ed_t * ed; __u32 edINFO; + __u32 tdINFO; td_t * td = NULL, * td_next = NULL, * tdHeadP = NULL, * tdTailP; __u32 * td_p; int ctrl = 0, bulk = 0; @@ -1141,16 +1194,25 @@ tdHeadP = bus_to_virt (le32_to_cpup (&ed->hwHeadP) & 0xfffffff0); edINFO = le32_to_cpup (&ed->hwINFO); td_p = &ed->hwHeadP; - + for (td = tdHeadP; td != tdTailP; td = td_next) { urb_t * urb = td->urb; urb_priv_t * urb_priv = td->urb->hcpriv; td_next = bus_to_virt (le32_to_cpup (&td->hwNextTD) & 0xfffffff0); if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) { + tdINFO = le32_to_cpup (&td->hwINFO); + if (TD_CC_GET (tdINFO) < 0xE) dl_transfer_length (td); *td_p = td->hwNextTD | (*td_p & cpu_to_le32 (0x3)); if(++ (urb_priv->td_cnt) == urb_priv->length) urb_rm_priv (urb); + if (urb->transfer_flags & USB_ASYNC_UNLINK) { + usb_dec_dev_use (urb->dev); + urb->status = -ECONNRESET; + urb->complete (urb); + } else { + wake_up (&op_wakeup); + } } else { td_p = &td->hwNextTD; } @@ -1167,7 +1229,7 @@ } else { ed->state &= ~ED_URB_DEL; - ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP); + ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP); } if ((ed->type & 3) == CTRL) ctrl |= 1; @@ -1185,6 +1247,8 @@ spin_unlock_irqrestore (&usb_ed_lock, flags); } + + /*-------------------------------------------------------------------------*/ /* td done list */ @@ -1193,12 +1257,11 @@ { td_t * td_list_next = NULL; ed_t * ed; - int dlen = 0; int cc = 0; urb_t * urb; urb_priv_t * urb_priv; - __u32 tdINFO, tdBE, tdCBP, edHeadP, edTailP; - __u16 tdPSW; + __u32 tdINFO, edHeadP, edTailP; + unsigned long flags; while (td_list) { @@ -1207,40 +1270,11 @@ urb = td_list->urb; urb_priv = urb->hcpriv; tdINFO = le32_to_cpup (&td_list->hwINFO); - tdBE = le32_to_cpup (&td_list->hwBE); - tdCBP = le32_to_cpup (&td_list->hwCBP); ed = td_list->ed; - if (td_list->type & ST_ADDR) - urb->actual_length = 0; - - if (td_list->type & ADD_LEN) { /* accumulate length of multi td transfers */ - if (tdINFO & TD_ISO) { - tdPSW = le16_to_cpu (td_list->hwPSW[0]); - cc = (tdPSW >> 12) & 0xF; - if (cc < 0xE) { - if (usb_pipeout(urb->pipe)) { - dlen = urb->iso_frame_desc[td_list->index].length; - } else { - dlen = tdPSW & 0x3ff; - } - urb->actual_length += dlen; - urb->iso_frame_desc[td_list->index].actual_length = dlen; - if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN)) - cc = TD_CC_NOERROR; - - urb->iso_frame_desc[td_list->index].status = cc_to_error[cc]; - } - } else { - if (tdBE != 0) { - if (td_list->hwCBP == 0) - urb->actual_length = bus_to_virt (tdBE) - urb->transfer_buffer + 1; - else - urb->actual_length = bus_to_virt (tdCBP) - urb->transfer_buffer; - } - } - } + dl_transfer_length(td_list); + /* error code of transfer */ cc = TD_CC_GET (tdINFO); if( cc == TD_CC_STALL) usb_endpoint_halt(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); @@ -1936,11 +1970,11 @@ { unsigned long mem_base; - mem_base = dev->resource[0].start; if (pci_enable_device(dev) < 0) return -ENODEV; pci_set_master (dev); + mem_base = dev->resource[0].start; mem_base = (unsigned long) ioremap_nocache (mem_base, 4096); if (!mem_base) { diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/usb-ohci.h linux/drivers/usb/usb-ohci.h --- v2.3.99-pre8/linux/drivers/usb/usb-ohci.h Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/usb-ohci.h Tue May 23 08:22:22 2000 @@ -432,7 +432,7 @@ static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned int pipe, int interval, int load); static void ep_rm_ed(struct usb_device * usb_dev, ed_t * ed); /* td */ -static void td_fill(unsigned int info, void * data, int len, urb_t * urb, int type, int index); +static void td_fill(unsigned int info, void * data, int len, urb_t * urb, int index); static void td_submit_urb(urb_t * urb); /* root hub */ static int rh_submit_urb(urb_t * urb); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/usb-storage.c linux/drivers/usb/usb-storage.c --- v2.3.99-pre8/linux/drivers/usb/usb-storage.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/usb-storage.c Sat May 20 10:18:21 2000 @@ -1,7 +1,10 @@ /* Driver for USB Mass Storage compliant devices * - * (c) 1999 Michael Gee (michael@linuxspecific.com) - * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) + * Initial work by: + * (c) 1999 Michael Gee (michael@linuxspecific.com) + * + * Current development and maintainance by: + * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * * This driver is based on the 'USB Mass Storage Class' document. This * describes in detail the protocol used to communicate with such @@ -16,6 +19,9 @@ * * Also, for certain devices, the interrupt endpoint is used to convey * status of a command. + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. */ #include @@ -111,10 +117,15 @@ struct semaphore ip_waitq; /* for CBI interrupts */ int ip_wanted; /* is an IRQ expected? */ + /* interrupt communications data */ struct semaphore irq_urb_sem; /* to protect irq_urb */ struct urb *irq_urb; /* for USB int requests */ unsigned char irqbuf[2]; /* buffer for USB IRQ */ + /* control and bulk communications data */ + struct semaphore current_urb_sem; /* to protect irq_urb */ + struct urb *current_urb; /* non-int USB requests */ + /* mutual exclusion structures */ struct semaphore notify; /* thread begin/end */ struct semaphore sleeper; /* to sleep the thread on */ @@ -147,6 +158,155 @@ * Data transfer routines ***********************************************************************/ +/* This is the completion handler which will wake us up when an URB + * completes. + */ +static void usb_stor_blocking_completion(urb_t *urb) +{ + api_wrapper_data *awd = (api_wrapper_data *)urb->context; + + if (waitqueue_active(awd->wakeup)) + wake_up(awd->wakeup); +} + +/* This is our function to emulate usb_control_msg() but give us enough + * access to make aborts/resets work + */ +int usb_stor_control_msg(struct us_data *us, unsigned int pipe, + u8 request, u8 requesttype, u16 value, u16 index, + void *data, u16 size) +{ + DECLARE_WAITQUEUE(wait, current); + DECLARE_WAIT_QUEUE_HEAD(wqh); + api_wrapper_data awd; + int status; + devrequest *dr; + + /* allocate the device request structure */ + dr = kmalloc(sizeof(devrequest), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + /* fill in the structure */ + dr->requesttype = requesttype; + dr->request = request; + dr->value = cpu_to_le16(value); + dr->index = cpu_to_le16(index); + dr->length = cpu_to_le16(size); + + /* set up data structures for the wakeup system */ + awd.wakeup = &wqh; + awd.handler = 0; + init_waitqueue_head(&wqh); + add_wait_queue(&wqh, &wait); + + /* lock the URB */ + down(&(us->current_urb_sem)); + + /* fill the URB */ + FILL_CONTROL_URB(us->current_urb, us->pusb_dev, pipe, + (unsigned char*) dr, data, size, + usb_stor_blocking_completion, &awd); + + /* submit the URB */ + set_current_state(TASK_UNINTERRUPTIBLE); + status = usb_submit_urb(us->current_urb); + if (status) { + /* something went wrong */ + up(&(us->current_urb_sem)); + remove_wait_queue(&wqh, &wait); + kfree(dr); + return status; + } + + /* wait for the completion of the URB */ + up(&(us->current_urb_sem)); + if (us->current_urb->status == -EINPROGRESS) + schedule_timeout(10*HZ); + down(&(us->current_urb_sem)); + + /* we either timed out or got woken up -- clean up either way */ + set_current_state(TASK_RUNNING); + remove_wait_queue(&wqh, &wait); + + /* did we time out? */ + if (us->current_urb->status == -EINPROGRESS) { + US_DEBUGP("usb_stor_control_msg() timeout\n"); + usb_unlink_urb(us->current_urb); + status = -ETIMEDOUT; + } else + status = us->current_urb->status; + + /* return the actual length of the data transferred if no error*/ + if (status >= 0) + status = us->current_urb->actual_length; + + /* release the lock and return status */ + up(&(us->current_urb_sem)); + kfree(dr); + return status; +} + +/* This is our function to emulate usb_bulk_msg() but give us enough + * access to make aborts/resets work + */ +int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe, + unsigned int len, unsigned int *act_len) +{ + DECLARE_WAITQUEUE(wait, current); + DECLARE_WAIT_QUEUE_HEAD(wqh); + api_wrapper_data awd; + int status; + + /* set up data structures for the wakeup system */ + awd.wakeup = &wqh; + awd.handler = 0; + init_waitqueue_head(&wqh); + add_wait_queue(&wqh, &wait); + + /* lock the URB */ + down(&(us->current_urb_sem)); + + /* fill the URB */ + FILL_BULK_URB(us->current_urb, us->pusb_dev, pipe, data, len, + usb_stor_blocking_completion, &awd); + + /* submit the URB */ + set_current_state(TASK_UNINTERRUPTIBLE); + status = usb_submit_urb(us->current_urb); + if (status) { + /* something went wrong */ + up(&(us->current_urb_sem)); + remove_wait_queue(&wqh, &wait); + return status; + } + + /* wait for the completion of the URB */ + up(&(us->current_urb_sem)); + if (us->current_urb->status == -EINPROGRESS) + schedule_timeout(10*HZ); + down(&(us->current_urb_sem)); + + /* we either timed out or got woken up -- clean up either way */ + set_current_state(TASK_RUNNING); + remove_wait_queue(&wqh, &wait); + + /* did we time out? */ + if (us->current_urb->status == -EINPROGRESS) { + US_DEBUGP("usb_stor_bulk_msg() timeout\n"); + usb_unlink_urb(us->current_urb); + status = -ETIMEDOUT; + } else + status = us->current_urb->status; + + /* return the actual length of the data transferred */ + *act_len = us->current_urb->actual_length; + + /* release the lock and return status */ + up(&(us->current_urb_sem)); + return status; +} + /* * Transfer one SCSI scatter-gather buffer via bulk transfer * @@ -158,26 +318,33 @@ * timeout limit. Thus we don't have to worry about it for individual * packets. */ -static int us_transfer_partial(struct us_data *us, int pipe, - char *buf, int length) +static int us_transfer_partial(struct us_data *us, char *buf, int length) { int result; int partial; + int pipe; + + /* calculate the appropriate pipe information */ + if (US_DIRECTION(us->srb->cmnd[0])) + pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); + else + pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); /* transfer the data */ - US_DEBUGP("Bulk xfer 0x%x(%d)\n", (unsigned int)buf, length); - result = usb_bulk_msg(us->pusb_dev, pipe, buf, length, &partial, 5*HZ); - US_DEBUGP("bulk_msg returned %d xferred %d/%d\n", + US_DEBUGP("us_transfer_partial(): xfer %d bytes\n", length); + result = usb_stor_bulk_msg(us, buf, pipe, length, &partial); + US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %d/%d\n", result, partial, length); - + /* if we stall, we need to clear it before we go on */ if (result == -EPIPE) { US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); usb_clear_halt(us->pusb_dev, pipe); } - + /* did we send all the data? */ if (partial == length) { + US_DEBUGP("us_transfer_partial(): transfer complete\n"); return US_BULK_TRANSFER_GOOD; } @@ -186,7 +353,17 @@ /* NAK - that means we've retried a few times allready */ if (result == -ETIMEDOUT) { US_DEBUGP("us_transfer_partial(): device NAKed\n"); + return US_BULK_TRANSFER_FAILED; } + + /* -ENOENT -- we canceled this transfer */ + if (result == -ENOENT) { + US_DEBUGP("us_transfer_partial(): transfer aborted\n"); + return US_BULK_TRANSFER_ABORTED; + } + + /* the catch-all case */ + US_DEBUGP("us_transfer_partial(): unknown error\n"); return US_BULK_TRANSFER_FAILED; } @@ -203,21 +380,12 @@ * function simply determines if we're going to use scatter-gather or not, * and acts appropriately. For now, it also re-interprets the error codes. */ -static void us_transfer(Scsi_Cmnd *srb, int dir_in) +static void us_transfer(Scsi_Cmnd *srb, struct us_data* us, int dir_in) { - struct us_data *us; int i; int result = -1; - unsigned int pipe; struct scatterlist *sg; - /* calculate the appropriate pipe information */ - us = (struct us_data*) srb->host_scribble; - if (dir_in) - pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); - else - pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); - /* are we scatter-gathering? */ if (srb->use_sg) { @@ -226,7 +394,7 @@ */ sg = (struct scatterlist *) srb->request_buffer; for (i = 0; i < srb->use_sg; i++) { - result = us_transfer_partial(us, pipe, sg[i].address, + result = us_transfer_partial(us, sg[i].address, sg[i].length); if (result) break; @@ -234,7 +402,7 @@ } else /* no scatter-gather, just make the request */ - result = us_transfer_partial(us, pipe, srb->request_buffer, + result = us_transfer_partial(us, srb->request_buffer, srb->request_bufflen); /* return the result in the data structure itself */ @@ -433,6 +601,8 @@ /* * Control/Bulk/Interrupt transport */ + +/* The interrupt handler for CBI devices */ static void CBI_irq(struct urb *urb) { struct us_data *us = (struct us_data *)urb->context; @@ -465,13 +635,13 @@ /* COMMAND STAGE */ /* let's send the command via the control pipe */ - result = usb_control_msg(us->pusb_dev, - usb_sndctrlpipe(us->pusb_dev,0), US_CBI_ADSC, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, - us->ifnum, srb->cmnd, srb->cmd_len, HZ*5); + result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0), + US_CBI_ADSC, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, + us->ifnum, srb->cmnd, srb->cmd_len); /* check the return code for the command */ - US_DEBUGP("Call to usb_control_msg() returned %d\n", result); + US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result); if (result < 0) { /* STALL must be cleared when they are detected */ if (result == -EPIPE) { @@ -493,7 +663,7 @@ /* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if (us_transfer_length(srb, us)) { - us_transfer(srb, US_DIRECTION(srb->cmnd[0])); + us_transfer(srb, us, US_DIRECTION(srb->cmnd[0])); US_DEBUGP("CBI data stage result is 0x%x\n", srb->result); } @@ -561,15 +731,14 @@ /* COMMAND STAGE */ /* let's send the command via the control pipe */ - result = usb_control_msg(us->pusb_dev, - usb_sndctrlpipe(us->pusb_dev,0), US_CBI_ADSC, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, - us->ifnum, srb->cmnd, srb->cmd_len, HZ*5); + result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0), + US_CBI_ADSC, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, + us->ifnum, srb->cmnd, srb->cmd_len); /* check the return code for the command */ + US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result); if (result < 0) { - US_DEBUGP("Call to usb_control_msg() returned %d\n", result); - /* a stall is a fatal condition from the device */ if (result == -EPIPE) { US_DEBUGP("-- Stall on control pipe. Clearing\n"); @@ -587,7 +756,7 @@ /* DATA STAGE */ /* transfer the data payload for this command, if one exists*/ if (us_transfer_length(srb, us)) { - us_transfer(srb, US_DIRECTION(srb->cmnd[0])); + us_transfer(srb, us, US_DIRECTION(srb->cmnd[0])); US_DEBUGP("CB data stage result is 0x%x\n", srb->result); } @@ -602,6 +771,39 @@ /* * Bulk only transport */ + +/* Determine what the maximum LUN supported is */ +static int Bulk_max_lun(struct us_data *us) +{ + unsigned char data; + int result; + int pipe; + + /* issue the command */ + pipe = usb_rcvctrlpipe(us->pusb_dev, 0); + result = usb_control_msg(us->pusb_dev, pipe, + US_BULK_GET_MAX_LUN, + USB_DIR_IN | USB_TYPE_CLASS | + USB_RECIP_INTERFACE, + 0, us->ifnum, &data, sizeof(data), HZ); + + US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", + result, data); + + /* if we have a successful request, return the result */ + if (!result) + return data; + + /* if we get a STALL, clear the stall */ + if (result == -EPIPE) { + US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); + usb_clear_halt(us->pusb_dev, pipe); + } + + /* return the default -- no LUNs */ + return 0; +} + static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us) { struct bulk_cb_wrap bcb; @@ -629,8 +831,8 @@ US_DEBUGP("Bulk command S 0x%x T 0x%x LUN %d L %d F %d CL %d\n", le32_to_cpu(bcb.Signature), bcb.Tag, bcb.Lun, bcb.DataTransferLength, bcb.Flags, bcb.Length); - result = usb_bulk_msg(us->pusb_dev, pipe, &bcb, - US_BULK_CB_WRAP_LEN, &partial, HZ*5); + result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN, + &partial); US_DEBUGP("Bulk command transfer result=%d\n", result); /* if we stall, we need to clear it before we go on */ @@ -643,7 +845,7 @@ if (result == 0) { /* send/receive data payload, if there is any */ if (bcb.DataTransferLength) { - us_transfer(srb, bcb.Flags); + us_transfer(srb, us, bcb.Flags); US_DEBUGP("Bulk data transfer result 0x%x\n", srb->result); } @@ -658,8 +860,8 @@ /* get CSW for device status */ US_DEBUGP("Attempting to get CSW...\n"); - result = usb_bulk_msg(us->pusb_dev, pipe, &bcs, - US_BULK_CS_WRAP_LEN, &partial, HZ*2); + result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN, + &partial); /* did the attempt to read the CSW fail? */ if (result == -EPIPE) { @@ -668,8 +870,8 @@ /* get the status again */ US_DEBUGP("Attempting to get CSW (2nd try)...\n"); - result = usb_bulk_msg(us->pusb_dev, pipe, &bcs, - US_BULK_CS_WRAP_LEN, &partial, HZ*2); + result = usb_stor_bulk_msg(us, &bcs, pipe, + US_BULK_CS_WRAP_LEN, &partial); /* if it fails again, we need a reset and return an error*/ if (result == -EPIPE) { @@ -1025,9 +1227,9 @@ result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0), - US_BULK_RESET, + US_BULK_RESET_REQUEST, USB_TYPE_CLASS | USB_RECIP_INTERFACE, - US_BULK_RESET_HARD, us->ifnum, NULL, 0, HZ*5); + 0, us->ifnum, NULL, 0, HZ*5); if (result < 0) US_DEBUGP("Bulk hard reset failed %d\n", result); @@ -1049,7 +1251,7 @@ static const char* us_info(struct Scsi_Host *host) { - return "SCSI emulation for USB Mass Storage devices\n"; + return "SCSI emulation for USB Mass Storage devices"; } /* detect a virtual adapter (always works) */ @@ -1109,6 +1311,7 @@ /* free the data structure we were using */ US_DEBUGP("-- freeing private host data structure\n"); + kfree(us->current_urb); kfree(us); (struct us_data*)psh->hostdata[0] = NULL; @@ -1289,22 +1492,11 @@ }; static unsigned char sense_notready[] = { - 0x70, /* current error */ - 0x00, - 0x02, /* not ready */ - 0x00, - 0x00, - 0x0a, /* additional length */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x04, /* not ready */ - 0x03, /* manual intervention */ - 0x00, - 0x00, - 0x00, - 0x00 + [0] = 0x70, /* current error */ + [2] = 0x02, /* not ready */ + [5] = 0x0a, /* additional length */ + [10] = 0x04, /* not ready */ + [11] = 0x03 /* manual intervention */ }; static int usb_stor_control_thread(void * __us) @@ -1429,25 +1621,31 @@ return 0; } +/* This is the list of devices we recognize, along with their flag data */ static struct us_unusual_dev us_unusual_dev_list[] = { + { 0x03f0, 0x0107, 0x0200, + "HP USB CD-Writer Plus", US_SC_8070, US_PR_CB, 0}, + { 0x04e6, 0x0001, 0x0200, + "Matshita LS-120", US_SC_8020, US_PR_CB, US_FL_SINGLE_LUN}, + { 0x04e6, 0x0002, 0x0100, + "Shuttle eUSCSI Bridge", US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, + { 0x04e6, 0x0006, 0x0100, + "Shuttle eUSB MMC Adapter", US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN}, { 0x057b, 0x0000, 0x0114, - "Y-E Data Flashbuster-U", US_SC_UFI, US_PR_CB, US_FL_SINGLE_LUN }, + "Y-E Data Flashbuster-U", US_SC_UFI, US_PR_CB, US_FL_SINGLE_LUN}, { 0x059b, 0x0030, 0x0100, - "Iomega Zip 250", US_SC_SCSI, US_PR_BULK, US_FL_SINGLE_LUN }, + "Iomega Zip 250", US_SC_SCSI, US_PR_BULK, US_FL_SINGLE_LUN}, + { 0x0693, 0x0002, 0x0100, + "Hagiwara FlashGate SmartMedia", US_SC_SCSI, US_PR_BULK, + US_FL_ALT_LENGTH}, { 0x0781, 0x0001, 0x0200, - "Sandisk ImageMate (w/eject button)", US_SC_SCSI, US_PR_CB, - US_FL_SINGLE_LUN | US_FL_START_STOP }, + "Sandisk ImageMate (SDDR-01)", US_SC_SCSI, US_PR_CB, + US_FL_SINGLE_LUN | US_FL_START_STOP}, { 0x0781, 0x0002, 0x0009, - "** SECRET DEVICE **", US_SC_SCSI, US_PR_BULK, - US_FL_SINGLE_LUN | US_FL_IGNORE_SER }, + "Sandisk Imagemate (SDDR-31)", US_SC_SCSI, US_PR_BULK, + US_FL_SINGLE_LUN | US_FL_IGNORE_SER}, { 0x07af, 0x0005, 0x0100, "Microtech USB-SCSI-HD50", US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, - { 0x04e6, 0x0002, 0x0100, - "Shuttle eUSCSI Bridge", US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, - { 0x04e6, 0x0006, 0x0100, - "Shuttle eUSB MMC Adapter", US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN}, - { 0x03f0, 0x0107, 0x0200, - "HP USB CD-Writer Plus", US_SC_8070, US_PR_CB, 0}, { 0x0000, 0x0000, 0x0, "", 0, 0, 0} }; @@ -1713,12 +1911,20 @@ } memset(ss, 0, sizeof(struct us_data)); + /* allocate the URB we're going to use */ + ss->current_urb = usb_alloc_urb(0); + if (!ss->current_urb) { + kfree(ss); + return NULL; + } + /* Initialize the mutexes only when the struct is new */ init_MUTEX_LOCKED(&(ss->sleeper)); init_MUTEX_LOCKED(&(ss->notify)); init_MUTEX_LOCKED(&(ss->ip_waitq)); init_MUTEX(&(ss->queue_exclusion)); init_MUTEX(&(ss->irq_urb_sem)); + init_MUTEX(&(ss->current_urb_sem)); init_MUTEX(&(ss->dev_semaphore)); /* copy over the subclass and protocol data */ @@ -1774,11 +1980,14 @@ ss->transport_name = "Bulk"; ss->transport = Bulk_transport; ss->transport_reset = Bulk_reset; + /* FIXME: for testing purposes only */ + Bulk_max_lun(ss); break; default: ss->transport_name = "Unknown"; up(&us_list_semaphore); + kfree(ss->current_urb); kfree(ss); return NULL; break; @@ -1802,6 +2011,7 @@ US_DEBUGP("contact mdharm-usb@one-eyed-alien.net\n"); US_DEBUGP("if you see this message.\n"); up(&us_list_semaphore); + kfree(ss->current_urb); kfree(ss); return NULL; break; @@ -1824,6 +2034,7 @@ default: ss->protocol_name = "Unknown"; up(&us_list_semaphore); + kfree(ss->current_urb); kfree(ss); return NULL; break; @@ -1859,6 +2070,7 @@ if (ss->pid < 0) { printk(KERN_WARNING USB_STORAGE "Unable to start control thread\n"); + kfree(ss->current_urb); kfree(ss); return NULL; } diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/usb-storage.h linux/drivers/usb/usb-storage.h --- v2.3.99-pre8/linux/drivers/usb/usb-storage.h Thu May 11 15:30:08 2000 +++ linux/drivers/usb/usb-storage.h Sat May 20 10:18:21 2000 @@ -77,16 +77,17 @@ #define US_BULK_STAT_FAIL 1 #define US_BULK_STAT_PHASE 2 -#define US_BULK_RESET 0xff -#define US_BULK_RESET_SOFT 1 -#define US_BULK_RESET_HARD 0 +/* bulk-only class specific requests */ +#define US_BULK_RESET_REQUEST 0xff +#define US_BULK_GET_MAX_LUN 0xfe /* * us_bulk_transfer() return codes */ -#define US_BULK_TRANSFER_GOOD 0 -#define US_BULK_TRANSFER_SHORT 1 -#define US_BULK_TRANSFER_FAILED 2 +#define US_BULK_TRANSFER_GOOD 0 /* good transfer */ +#define US_BULK_TRANSFER_SHORT 1 /* transfered less than expected */ +#define US_BULK_TRANSFER_FAILED 2 /* transfer died in the middle */ +#define US_BULK_TRANSFER_ABORTED 3 /* transfer canceled */ /* * Transport return codes @@ -95,6 +96,7 @@ #define USB_STOR_TRANSPORT_GOOD 0 /* Transport good, command good */ #define USB_STOR_TRANSPORT_FAILED 1 /* Transport good, command failed */ #define USB_STOR_TRANSPORT_ERROR 2 /* Transport bad (i.e. device dead) */ +#define USB_STOR_TRANSPORT_ABORTED 3 /* Transport aborted */ /* * CBI accept device specific command diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c --- v2.3.99-pre8/linux/drivers/usb/usb-uhci.c Thu May 11 15:30:08 2000 +++ linux/drivers/usb/usb-uhci.c Mon May 15 12:05:15 2000 @@ -12,7 +12,7 @@ * (C) Copyright 1999 Johannes Erdfelt * (C) Copyright 1999 Randy Dunlap * - * $Id: usb-uhci.c,v 1.228 2000/04/02 19:55:51 acher Exp $ + * $Id: usb-uhci.c,v 1.231 2000/05/13 15:34:17 acher Exp $ */ #include @@ -48,7 +48,7 @@ /* This enables an extra UHCI slab for memory debugging */ #define DEBUG_SLAB -#define VERSTR "$Revision: 1.228 $ time " __TIME__ " " __DATE__ +#define VERSTR "$Revision: 1.231 $ time " __TIME__ " " __DATE__ #include #include "usb-uhci.h" @@ -109,10 +109,10 @@ while (q != &s->free_desc) { qh = list_entry (q, uhci_desc_t, horizontal); + q=qh->horizontal.prev; + if ((qh->last_used!=now) || force) delete_qh(s,qh); - - q=qh->horizontal.prev; } } /*-------------------------------------------------------------------*/ @@ -1142,6 +1142,12 @@ if (!(urb->transfer_flags & USB_TIMEOUT_KILLED)) urb->status = -ENOENT; // now the urb is really dead + switch (usb_pipetype (pipe)) { + case PIPE_ISOCHRONOUS: + case PIPE_INTERRUPT: + uhci_clean_iso_step2(s, urb_priv); + break; + } usb_dec_dev_use (dev); #ifdef DEBUG_SLAB @@ -1149,12 +1155,7 @@ #else kfree (urb_priv); #endif - switch (usb_pipetype (pipe)) { - case PIPE_ISOCHRONOUS: - case PIPE_INTERRUPT: - uhci_clean_iso_step2(s, urb_priv); - break; - } + list_del (&urb->urb_list); } } @@ -1168,7 +1169,9 @@ async_dbg("unlink_urb_async called %p",urb); - if (urb->status == -EINPROGRESS) { + if ((urb->status == -EINPROGRESS) || + ((usb_pipetype (urb->pipe) == PIPE_INTERRUPT) && ((urb_priv_t*)urb->hcpriv)->flags)) + { ((urb_priv_t*)urb->hcpriv)->started = ~0; dequeue_urb (s, urb); @@ -1560,7 +1563,7 @@ urb->hcpriv = urb_priv; INIT_LIST_HEAD (&urb_priv->desc_list); - urb_priv->short_control_packet = 0; + urb_priv->flags = 0; dbg("submit_urb: scheduling %p", urb); urb_priv->next_queued_urb = NULL; urb_priv->prev_queued_urb = NULL; @@ -2151,7 +2154,7 @@ status stage is completed */ - if (urb_priv->short_control_packet && + if (urb_priv->flags && ((qh->hw.qh.element == UHCI_PTR_TERM) ||(!(last_desc->hw.td.status & TD_CTRL_ACTIVE)))) goto transfer_finished; @@ -2199,7 +2202,7 @@ dbg("short packet during control transfer, retrigger status stage @ %p",last_desc); //uhci_show_td (desc); //uhci_show_td (last_desc); - urb_priv->short_control_packet=1; + urb_priv->flags = 1; // mark as short control packet return 0; } } @@ -2280,35 +2283,43 @@ if (urb->complete) { //dbg("process_interrupt: calling completion, status %i",status); urb->status = status; - + ((urb_priv_t*)urb->hcpriv)->flags=1; // if unlink_urb is called during completion + spin_unlock(&s->urb_list_lock); urb->complete ((struct urb *) urb); spin_lock(&s->urb_list_lock); - - urb->status = -EINPROGRESS; + + ((urb_priv_t*)urb->hcpriv)->flags=0; } + + if ((urb->status != -ECONNABORTED) && (urb->status != ECONNRESET) && + (urb->status != -ENOENT)) { - // Recycle INT-TD if interval!=0, else mark TD as one-shot - if (urb->interval) { + urb->status = -EINPROGRESS; - desc->hw.td.info &= ~(1 << TD_TOKEN_TOGGLE); - if (status==0) { - ((urb_priv_t*)urb->hcpriv)->started=jiffies; - desc->hw.td.info |= (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), - usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE); - usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); - } else { - desc->hw.td.info |= (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), - usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE); + // Recycle INT-TD if interval!=0, else mark TD as one-shot + if (urb->interval) { + + desc->hw.td.info &= ~(1 << TD_TOKEN_TOGGLE); + if (status==0) { + ((urb_priv_t*)urb->hcpriv)->started=jiffies; + desc->hw.td.info |= (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), + usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE); + usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe)); + } else { + desc->hw.td.info |= (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), + usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE); + } + desc->hw.td.status= (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | + (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27); + mb(); + } + else { + uhci_unlink_urb_async(s, urb); + desc->hw.td.status &= ~TD_CTRL_IOC; // inactivate TD } - desc->hw.td.status= (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC | - (urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27); - mb(); - } - else { - desc->hw.td.status &= ~TD_CTRL_IOC; // inactivate TD } } @@ -2334,7 +2345,7 @@ dbg("process iso urb %p, %li, %i, %i, %i %08x",urb,jiffies,UHCI_GET_CURRENT_FRAME(s), urb->number_of_packets,mode,desc->hw.td.status); - for (i = 0; p != &urb_priv->desc_list; p = p->next, i++) { + for (i = 0; p != &urb_priv->desc_list; i++) { desc = list_entry (p, uhci_desc_t, desc_list); //uhci_show_td(desc); @@ -2378,8 +2389,9 @@ dbg("process_iso: %i: len:%d %08x status:%x", i, urb->iso_frame_desc[i].actual_length, desc->hw.td.status,urb->iso_frame_desc[i].status); - delete_desc (desc); list_del (p); + p = p->next; + delete_desc (desc); } dbg("process_iso: exit %i (%d), actual_len %i", i, ret,urb->actual_length); @@ -2823,7 +2835,6 @@ pci_read_config_byte (dev, PCI_CLASS_PROG, &type); if (type != 0) continue; - if (pci_enable_device (dev) < 0) continue; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/usb-uhci.h linux/drivers/usb/usb-uhci.h --- v2.3.99-pre8/linux/drivers/usb/usb-uhci.h Tue Apr 11 15:09:20 2000 +++ linux/drivers/usb/usb-uhci.h Mon May 15 12:05:15 2000 @@ -2,7 +2,7 @@ #define __LINUX_UHCI_H /* - $Id: usb-uhci.h,v 1.54 2000/04/02 19:55:53 acher Exp $ + $Id: usb-uhci.h,v 1.55 2000/05/13 12:50:30 acher Exp $ */ #define MODNAME "usb-uhci" #define UHCI_LATENCY_TIMER 0 @@ -160,7 +160,7 @@ uhci_desc_t *bottom_qh; uhci_desc_t *next_qh; // next helper QH char use_loop; - char short_control_packet; + char flags; } urb_priv_t, *purb_priv_t; struct virt_root_hub { diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/wacom.c linux/drivers/usb/wacom.c --- v2.3.99-pre8/linux/drivers/usb/wacom.c Mon Mar 27 08:08:28 2000 +++ linux/drivers/usb/wacom.c Sat May 20 11:24:15 2000 @@ -104,8 +104,8 @@ int distance_max; void (*irq)(struct urb *urb); unsigned long evbit; - unsigned long relbit; unsigned long absbit; + unsigned long relbit; unsigned long btnbit; unsigned long digibit; }; diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c --- v2.3.99-pre8/linux/drivers/video/cyber2000fb.c Fri May 12 14:18:55 2000 +++ linux/drivers/video/cyber2000fb.c Mon May 15 12:00:33 2000 @@ -1636,3 +1636,5 @@ module_init(cyber2000fb_init); #endif module_exit(cyberpro_exit); + +MODULE_DEVICE_TABLE(pci, cyberpro_pci_table); diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/video/cyber2000fb.h linux/drivers/video/cyber2000fb.h --- v2.3.99-pre8/linux/drivers/video/cyber2000fb.h Fri May 12 14:18:55 2000 +++ linux/drivers/video/cyber2000fb.h Mon May 15 12:10:26 2000 @@ -3,6 +3,7 @@ * * Integraphics Cyber2000 frame buffer device */ +#include #define cyber2000_outb(dat,reg) writeb(dat, CyberRegs + reg) #define cyber2000_outw(dat,reg) writew(dat, CyberRegs + reg) diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/video/newport_con.c linux/drivers/video/newport_con.c --- v2.3.99-pre8/linux/drivers/video/newport_con.c Tue Aug 31 17:29:14 1999 +++ linux/drivers/video/newport_con.c Sat May 13 08:33:26 2000 @@ -1,9 +1,9 @@ -/* $Id: newport_con.c,v 1.13 1999/04/11 10:37:08 ulfc Exp $ +/* $Id: newport_con.c,v 1.14 1999/06/24 01:10:24 ulfc Exp $ * * newport_con.c: Abscon for newport hardware * * (C) 1998 Thomas Bogendoerfer (tsbogend@alpha.franken.de) - * (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se) + * (C) 1999 Ulf Carlsson (ulfc@thepuffingruop.com) * * This driver is based on sgicons.c and cons_newport. * @@ -26,14 +26,19 @@ #include #include #include -#include +#include